Reference count the fonts used in the text widget.
authorOwen Taylor <otaylor@redhat.com>
Tue, 25 Aug 1998 00:06:38 +0000 (00:06 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Tue, 25 Aug 1998 00:06:38 +0000 (00:06 +0000)
Mon Aug 24 18:37:15 1998  Owen Taylor  <otaylor@redhat.com>

* gtk/gtktext.c: Reference count the fonts used in
the text widget.

* gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation
freeing functions to be more consistent, and more
convenient; leave the old names in for backwards compatibility.

* gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the
allocations in pseudo-color colormaps to greatly reduce
calls to XAllocColor. Keep a per-colormap hashtable to
speed up finding if there is an already-allocated matching
color.

* gdk/gdkcolor.c: Don't just match read the system colormap
when the colormap is created, but synchronize our copy
with the system colormap periodically.

* gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c:
Change XIM constants names to match GDK conventions

* gtk/testinput.c: Allow the drawing area to get the focus.

* gtk/testgtk.c: Change around the Text test to demonstrates
multiple fonts, use more colors.

* gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual()
so they work after a widget is unrealized.

* gtk/gtktext.[ch]: Remove the requirement that the text
widget be realized before adding text (!) Allocate colors
ourself, instead of requiring the caller allocate them.
Allow changing styles to work properly by keeping track
of the values for a certain property are default or
set explicitely.

* gtk/gtkmenu.h: Added some comments.

* gtk/gtkentry.c: Changes to match XIM constants.

* gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(),
for adding keyed data to drawables. (Uses g_dataset
internally)

* gdk/gdkpixmap.c: Keep track of the colors we allocate,
when creating an XPM - store them as user data for the GdkPixmap,
so we don't leak colors when we create pixmaps from XPM's.

Allocate memory for color information in large blocks instead of
as many little pieces.

37 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
TODO
gdk/gdk.c
gdk/gdk.h
gdk/gdkcolor.c
gdk/gdkpixmap.c
gdk/gdkprivate.h
gdk/gdktypes.h
gdk/gdkwindow.c
gdk/gdkx.h
gdk/x11/gdkcolor-x11.c
gdk/x11/gdkmain-x11.c
gdk/x11/gdkpixmap-x11.c
gdk/x11/gdkwindow-x11.c
gdk/x11/gdkx.h
gtk/gtk.defs
gtk/gtkentry.c
gtk/gtkmenu.h
gtk/gtktext.c
gtk/gtktext.h
gtk/gtktypebuiltins.h
gtk/gtktypebuiltins_evals.c
gtk/gtktypebuiltins_ids.c
gtk/gtktypebuiltins_vars.c
gtk/gtkwidget.c
gtk/testgtk.c
gtk/testgtkrc
gtk/testinput.c
tests/testgtk.c
tests/testgtkrc
tests/testinput.c

index 6cefa1fc32b736579b31c6655d0c2a272814134f..65f98ce78e4b3b8252a32954559cfad59e840018 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,55 @@
+Mon Aug 24 18:37:15 1998  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktext.c: Reference count the fonts used in
+       the text widget.
+
+       * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation
+       freeing functions to be more consistent, and more 
+       convenient; leave the old names in for backwards compatibility.
+
+       * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the
+       allocations in pseudo-color colormaps to greatly reduce
+       calls to XAllocColor. Keep a per-colormap hashtable to
+       speed up finding if there is an already-allocated matching
+       color.
+
+       * gdk/gdkcolor.c: Don't just match read the system colormap
+       when the colormap is created, but synchronize our copy
+       with the system colormap periodically.
+       
+       * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: 
+       Change XIM constants names to match GDK conventions
+
+       * gtk/testinput.c: Allow the drawing area to get the focus.
+
+       * gtk/testgtk.c: Change around the Text test to demonstrates
+       multiple fonts, use more colors.
+
+       * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual()
+       so they work after a widget is unrealized.
+
+       * gtk/gtktext.[ch]: Remove the requirement that the text
+       widget be realized before adding text (!) Allocate colors
+       ourself, instead of requiring the caller allocate them.
+       Allow changing styles to work properly by keeping track
+       of the values for a certain property are default or
+       set explicitely.
+
+       * gtk/gtkmenu.h: Added some comments.
+
+       * gtk/gtkentry.c: Changes to match XIM constants.
+
+       * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(),
+       for adding keyed data to drawables. (Uses g_dataset
+       internally)
+
+       * gdk/gdkpixmap.c: Keep track of the colors we allocate,
+       when creating an XPM - store them as user data for the GdkPixmap,
+       so we don't leak colors when we create pixmaps from XPM's.
+
+       Allocate memory for color information in large blocks instead of 
+       as many little pieces.
+       
 Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org>
 
        * gdk/gdkrgb.c: removed some unused variables
index 6cefa1fc32b736579b31c6655d0c2a272814134f..65f98ce78e4b3b8252a32954559cfad59e840018 100644 (file)
@@ -1,3 +1,55 @@
+Mon Aug 24 18:37:15 1998  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktext.c: Reference count the fonts used in
+       the text widget.
+
+       * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation
+       freeing functions to be more consistent, and more 
+       convenient; leave the old names in for backwards compatibility.
+
+       * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the
+       allocations in pseudo-color colormaps to greatly reduce
+       calls to XAllocColor. Keep a per-colormap hashtable to
+       speed up finding if there is an already-allocated matching
+       color.
+
+       * gdk/gdkcolor.c: Don't just match read the system colormap
+       when the colormap is created, but synchronize our copy
+       with the system colormap periodically.
+       
+       * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: 
+       Change XIM constants names to match GDK conventions
+
+       * gtk/testinput.c: Allow the drawing area to get the focus.
+
+       * gtk/testgtk.c: Change around the Text test to demonstrates
+       multiple fonts, use more colors.
+
+       * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual()
+       so they work after a widget is unrealized.
+
+       * gtk/gtktext.[ch]: Remove the requirement that the text
+       widget be realized before adding text (!) Allocate colors
+       ourself, instead of requiring the caller allocate them.
+       Allow changing styles to work properly by keeping track
+       of the values for a certain property are default or
+       set explicitely.
+
+       * gtk/gtkmenu.h: Added some comments.
+
+       * gtk/gtkentry.c: Changes to match XIM constants.
+
+       * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(),
+       for adding keyed data to drawables. (Uses g_dataset
+       internally)
+
+       * gdk/gdkpixmap.c: Keep track of the colors we allocate,
+       when creating an XPM - store them as user data for the GdkPixmap,
+       so we don't leak colors when we create pixmaps from XPM's.
+
+       Allocate memory for color information in large blocks instead of 
+       as many little pieces.
+       
 Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org>
 
        * gdk/gdkrgb.c: removed some unused variables
index 6cefa1fc32b736579b31c6655d0c2a272814134f..65f98ce78e4b3b8252a32954559cfad59e840018 100644 (file)
@@ -1,3 +1,55 @@
+Mon Aug 24 18:37:15 1998  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktext.c: Reference count the fonts used in
+       the text widget.
+
+       * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation
+       freeing functions to be more consistent, and more 
+       convenient; leave the old names in for backwards compatibility.
+
+       * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the
+       allocations in pseudo-color colormaps to greatly reduce
+       calls to XAllocColor. Keep a per-colormap hashtable to
+       speed up finding if there is an already-allocated matching
+       color.
+
+       * gdk/gdkcolor.c: Don't just match read the system colormap
+       when the colormap is created, but synchronize our copy
+       with the system colormap periodically.
+       
+       * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: 
+       Change XIM constants names to match GDK conventions
+
+       * gtk/testinput.c: Allow the drawing area to get the focus.
+
+       * gtk/testgtk.c: Change around the Text test to demonstrates
+       multiple fonts, use more colors.
+
+       * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual()
+       so they work after a widget is unrealized.
+
+       * gtk/gtktext.[ch]: Remove the requirement that the text
+       widget be realized before adding text (!) Allocate colors
+       ourself, instead of requiring the caller allocate them.
+       Allow changing styles to work properly by keeping track
+       of the values for a certain property are default or
+       set explicitely.
+
+       * gtk/gtkmenu.h: Added some comments.
+
+       * gtk/gtkentry.c: Changes to match XIM constants.
+
+       * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(),
+       for adding keyed data to drawables. (Uses g_dataset
+       internally)
+
+       * gdk/gdkpixmap.c: Keep track of the colors we allocate,
+       when creating an XPM - store them as user data for the GdkPixmap,
+       so we don't leak colors when we create pixmaps from XPM's.
+
+       Allocate memory for color information in large blocks instead of 
+       as many little pieces.
+       
 Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org>
 
        * gdk/gdkrgb.c: removed some unused variables
index 6cefa1fc32b736579b31c6655d0c2a272814134f..65f98ce78e4b3b8252a32954559cfad59e840018 100644 (file)
@@ -1,3 +1,55 @@
+Mon Aug 24 18:37:15 1998  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktext.c: Reference count the fonts used in
+       the text widget.
+
+       * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation
+       freeing functions to be more consistent, and more 
+       convenient; leave the old names in for backwards compatibility.
+
+       * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the
+       allocations in pseudo-color colormaps to greatly reduce
+       calls to XAllocColor. Keep a per-colormap hashtable to
+       speed up finding if there is an already-allocated matching
+       color.
+
+       * gdk/gdkcolor.c: Don't just match read the system colormap
+       when the colormap is created, but synchronize our copy
+       with the system colormap periodically.
+       
+       * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: 
+       Change XIM constants names to match GDK conventions
+
+       * gtk/testinput.c: Allow the drawing area to get the focus.
+
+       * gtk/testgtk.c: Change around the Text test to demonstrates
+       multiple fonts, use more colors.
+
+       * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual()
+       so they work after a widget is unrealized.
+
+       * gtk/gtktext.[ch]: Remove the requirement that the text
+       widget be realized before adding text (!) Allocate colors
+       ourself, instead of requiring the caller allocate them.
+       Allow changing styles to work properly by keeping track
+       of the values for a certain property are default or
+       set explicitely.
+
+       * gtk/gtkmenu.h: Added some comments.
+
+       * gtk/gtkentry.c: Changes to match XIM constants.
+
+       * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(),
+       for adding keyed data to drawables. (Uses g_dataset
+       internally)
+
+       * gdk/gdkpixmap.c: Keep track of the colors we allocate,
+       when creating an XPM - store them as user data for the GdkPixmap,
+       so we don't leak colors when we create pixmaps from XPM's.
+
+       Allocate memory for color information in large blocks instead of 
+       as many little pieces.
+       
 Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org>
 
        * gdk/gdkrgb.c: removed some unused variables
index 6cefa1fc32b736579b31c6655d0c2a272814134f..65f98ce78e4b3b8252a32954559cfad59e840018 100644 (file)
@@ -1,3 +1,55 @@
+Mon Aug 24 18:37:15 1998  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktext.c: Reference count the fonts used in
+       the text widget.
+
+       * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation
+       freeing functions to be more consistent, and more 
+       convenient; leave the old names in for backwards compatibility.
+
+       * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the
+       allocations in pseudo-color colormaps to greatly reduce
+       calls to XAllocColor. Keep a per-colormap hashtable to
+       speed up finding if there is an already-allocated matching
+       color.
+
+       * gdk/gdkcolor.c: Don't just match read the system colormap
+       when the colormap is created, but synchronize our copy
+       with the system colormap periodically.
+       
+       * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: 
+       Change XIM constants names to match GDK conventions
+
+       * gtk/testinput.c: Allow the drawing area to get the focus.
+
+       * gtk/testgtk.c: Change around the Text test to demonstrates
+       multiple fonts, use more colors.
+
+       * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual()
+       so they work after a widget is unrealized.
+
+       * gtk/gtktext.[ch]: Remove the requirement that the text
+       widget be realized before adding text (!) Allocate colors
+       ourself, instead of requiring the caller allocate them.
+       Allow changing styles to work properly by keeping track
+       of the values for a certain property are default or
+       set explicitely.
+
+       * gtk/gtkmenu.h: Added some comments.
+
+       * gtk/gtkentry.c: Changes to match XIM constants.
+
+       * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(),
+       for adding keyed data to drawables. (Uses g_dataset
+       internally)
+
+       * gdk/gdkpixmap.c: Keep track of the colors we allocate,
+       when creating an XPM - store them as user data for the GdkPixmap,
+       so we don't leak colors when we create pixmaps from XPM's.
+
+       Allocate memory for color information in large blocks instead of 
+       as many little pieces.
+       
 Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org>
 
        * gdk/gdkrgb.c: removed some unused variables
index 6cefa1fc32b736579b31c6655d0c2a272814134f..65f98ce78e4b3b8252a32954559cfad59e840018 100644 (file)
@@ -1,3 +1,55 @@
+Mon Aug 24 18:37:15 1998  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktext.c: Reference count the fonts used in
+       the text widget.
+
+       * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation
+       freeing functions to be more consistent, and more 
+       convenient; leave the old names in for backwards compatibility.
+
+       * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the
+       allocations in pseudo-color colormaps to greatly reduce
+       calls to XAllocColor. Keep a per-colormap hashtable to
+       speed up finding if there is an already-allocated matching
+       color.
+
+       * gdk/gdkcolor.c: Don't just match read the system colormap
+       when the colormap is created, but synchronize our copy
+       with the system colormap periodically.
+       
+       * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: 
+       Change XIM constants names to match GDK conventions
+
+       * gtk/testinput.c: Allow the drawing area to get the focus.
+
+       * gtk/testgtk.c: Change around the Text test to demonstrates
+       multiple fonts, use more colors.
+
+       * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual()
+       so they work after a widget is unrealized.
+
+       * gtk/gtktext.[ch]: Remove the requirement that the text
+       widget be realized before adding text (!) Allocate colors
+       ourself, instead of requiring the caller allocate them.
+       Allow changing styles to work properly by keeping track
+       of the values for a certain property are default or
+       set explicitely.
+
+       * gtk/gtkmenu.h: Added some comments.
+
+       * gtk/gtkentry.c: Changes to match XIM constants.
+
+       * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(),
+       for adding keyed data to drawables. (Uses g_dataset
+       internally)
+
+       * gdk/gdkpixmap.c: Keep track of the colors we allocate,
+       when creating an XPM - store them as user data for the GdkPixmap,
+       so we don't leak colors when we create pixmaps from XPM's.
+
+       Allocate memory for color information in large blocks instead of 
+       as many little pieces.
+       
 Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org>
 
        * gdk/gdkrgb.c: removed some unused variables
index 6cefa1fc32b736579b31c6655d0c2a272814134f..65f98ce78e4b3b8252a32954559cfad59e840018 100644 (file)
@@ -1,3 +1,55 @@
+Mon Aug 24 18:37:15 1998  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktext.c: Reference count the fonts used in
+       the text widget.
+
+       * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation
+       freeing functions to be more consistent, and more 
+       convenient; leave the old names in for backwards compatibility.
+
+       * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the
+       allocations in pseudo-color colormaps to greatly reduce
+       calls to XAllocColor. Keep a per-colormap hashtable to
+       speed up finding if there is an already-allocated matching
+       color.
+
+       * gdk/gdkcolor.c: Don't just match read the system colormap
+       when the colormap is created, but synchronize our copy
+       with the system colormap periodically.
+       
+       * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: 
+       Change XIM constants names to match GDK conventions
+
+       * gtk/testinput.c: Allow the drawing area to get the focus.
+
+       * gtk/testgtk.c: Change around the Text test to demonstrates
+       multiple fonts, use more colors.
+
+       * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual()
+       so they work after a widget is unrealized.
+
+       * gtk/gtktext.[ch]: Remove the requirement that the text
+       widget be realized before adding text (!) Allocate colors
+       ourself, instead of requiring the caller allocate them.
+       Allow changing styles to work properly by keeping track
+       of the values for a certain property are default or
+       set explicitely.
+
+       * gtk/gtkmenu.h: Added some comments.
+
+       * gtk/gtkentry.c: Changes to match XIM constants.
+
+       * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(),
+       for adding keyed data to drawables. (Uses g_dataset
+       internally)
+
+       * gdk/gdkpixmap.c: Keep track of the colors we allocate,
+       when creating an XPM - store them as user data for the GdkPixmap,
+       so we don't leak colors when we create pixmaps from XPM's.
+
+       Allocate memory for color information in large blocks instead of 
+       as many little pieces.
+       
 Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org>
 
        * gdk/gdkrgb.c: removed some unused variables
diff --git a/TODO b/TODO
index 0be764de5e564d6945b42af354394cd67e4d3142..6f22b89b7c38771be8f602f179f7ae9b03110d7b 100644 (file)
--- a/TODO
+++ b/TODO
@@ -271,3 +271,5 @@ Text/Edit widget:
     [ From: Stefan Jeske <jeske@braunschweig.netsurf.de> ]
 
   - "changed" emitted when doing deletes on empty Text widget.
+
+  - Delete IC in editable->unrealize, not editable->finalize?
\ No newline at end of file
index 5573d100198ec243502508cf0d087ac9c557b75c..1932d7d3bc51ffbc8aeeb36ba534e339f63dbb69 100644 (file)
--- a/gdk/gdk.c
+++ b/gdk/gdk.c
@@ -446,15 +446,15 @@ gdk_init (int      *argc,
                  {
                    (*argv)[i++] = NULL;
                    if (strcmp ("none", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMPreeditNone);
+                     gdk_im_set_best_style (GDK_IM_PREEDIT_NONE);
                    else if (strcmp ("nothing", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMPreeditNothing);
+                     gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING);
                    else if (strcmp ("area", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMPreeditArea);
+                     gdk_im_set_best_style (GDK_IM_PREEDIT_AREA);
                    else if (strcmp ("position", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMPreeditPosition);
+                     gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION);
                    else if (strcmp ("callbacks", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMPreeditCallbacks);
+                     gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
                  }
              }
            else if (strcmp ("--xim-status", (*argv)[i]) == 0)
@@ -463,13 +463,13 @@ gdk_init (int      *argc,
                  {
                    (*argv)[i++] = NULL;
                    if (strcmp ("none", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMStatusNone);
+                     gdk_im_set_best_style (GDK_IM_STATUS_NONE);
                    else if (strcmp ("nothing", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMStatusNothing);
+                     gdk_im_set_best_style (GDK_IM_STATUS_NOTHING);
                    else if (strcmp ("area", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMStatusArea);
+                     gdk_im_set_best_style (GDK_IM_STATUS_AREA);
                    else if (strcmp ("callbacks", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMStatusCallbacks);
+                     gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
                  }
              }
 #endif
@@ -584,10 +584,10 @@ gdk_init (int      *argc,
   xim_using = FALSE;
   xim_im = NULL;
   xim_styles = NULL;
-  if (!(xim_best_allowed_style & GdkIMPreeditMask))
-    gdk_im_set_best_style (GdkIMPreeditCallbacks);
-  if (!(xim_best_allowed_style & GdkIMStatusMask))
-    gdk_im_set_best_style (GdkIMStatusCallbacks);
+  if (!(xim_best_allowed_style & GDK_IM_PREEDIT_MASK))
+    gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
+  if (!(xim_best_allowed_style & GDK_IM_STATUS_MASK))
+    gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
   xim_ic = NULL;
   xim_window = (GdkWindow*)NULL;
   
@@ -3570,34 +3570,34 @@ gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
   
   if (style1 == 0) return style2;
   if (style2 == 0) return style1;
-  if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask))
-      == (style2 & (GdkIMPreeditMask | GdkIMStatusMask)))
+  if ((style1 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))
+       == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)))
     return style1;
-  
-  s1 = style1 & GdkIMPreeditMask;
-  s2 = style2 & GdkIMPreeditMask;
+
+  s1 = style1 & GDK_IM_PREEDIT_MASK;
+  s2 = style2 & GDK_IM_PREEDIT_MASK;
   u = s1 | s2;
   if (s1 != s2) {
-    if (u & GdkIMPreeditCallbacks)
-      return (s1 == GdkIMPreeditCallbacks)? style1:style2;
-    else if (u & GdkIMPreeditPosition)
-      return (s1 == GdkIMPreeditPosition)? style1:style2;
-    else if (u & GdkIMPreeditArea)
-      return (s1 == GdkIMPreeditArea)? style1:style2;
-    else if (u & GdkIMPreeditNothing)
-      return (s1 == GdkIMPreeditNothing)? style1:style2;
+    if (u & GDK_IM_PREEDIT_CALLBACKS)
+      return (s1 == GDK_IM_PREEDIT_CALLBACKS)? style1:style2;
+    else if (u & GDK_IM_PREEDIT_POSITION)
+      return (s1 == GDK_IM_PREEDIT_POSITION)? style1:style2;
+    else if (u & GDK_IM_PREEDIT_AREA)
+      return (s1 == GDK_IM_PREEDIT_AREA)? style1:style2;
+    else if (u & GDK_IM_PREEDIT_NOTHING)
+      return (s1 == GDK_IM_PREEDIT_NOTHING)? style1:style2;
   } else {
-    s1 = style1 & GdkIMStatusMask;
-    s2 = style2 & GdkIMStatusMask;
+    s1 = style1 & GDK_IM_STATUS_MASK;
+    s2 = style2 & GDK_IM_STATUS_MASK;
     u = s1 | s2;
-    if ( u & GdkIMStatusCallbacks)
-      return (s1 == GdkIMStatusCallbacks)? style1:style2;
-    else if ( u & GdkIMStatusArea)
-      return (s1 == GdkIMStatusArea)? style1:style2;
-    else if ( u & GdkIMStatusNothing)
-      return (s1 == GdkIMStatusNothing)? style1:style2;
-    else if ( u & GdkIMStatusNone)
-      return (s1 == GdkIMStatusNone)? style1:style2;
+    if ( u & GDK_IM_STATUS_CALLBACKS)
+      return (s1 == GDK_IM_STATUS_CALLBACKS)? style1:style2;
+    else if ( u & GDK_IM_STATUS_AREA)
+      return (s1 == GDK_IM_STATUS_AREA)? style1:style2;
+    else if ( u & GDK_IM_STATUS_NOTHING)
+      return (s1 == GDK_IM_STATUS_NOTHING)? style1:style2;
+    else if ( u & GDK_IM_STATUS_NONE)
+      return (s1 == GDK_IM_STATUS_NONE)? style1:style2;
   }
   return 0; /* Get rid of stupid warning */
 }
@@ -3623,39 +3623,39 @@ gdk_im_decide_style (GdkIMStyle supported_style)
 GdkIMStyle
 gdk_im_set_best_style (GdkIMStyle style)
 {
-  if (style & GdkIMPreeditMask)
+  if (style & GDK_IM_PREEDIT_MASK)
     {
-      xim_best_allowed_style &= ~GdkIMPreeditMask;
-      
-      xim_best_allowed_style |= GdkIMPreeditNone;
-      if (!(style & GdkIMPreeditNone))
+      xim_best_allowed_style &= ~GDK_IM_PREEDIT_MASK;
+
+      xim_best_allowed_style |= GDK_IM_PREEDIT_NONE;
+      if (!(style & GDK_IM_PREEDIT_NONE))
        {
-         xim_best_allowed_style |= GdkIMPreeditNothing;
-         if (!(style & GdkIMPreeditNothing))
+         xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING;
+         if (!(style & GDK_IM_PREEDIT_NOTHING))
            {
-             xim_best_allowed_style |= GdkIMPreeditArea;
-             if (!(style & GdkIMPreeditArea))
+             xim_best_allowed_style |= GDK_IM_PREEDIT_AREA;
+             if (!(style & GDK_IM_PREEDIT_AREA))
                {
-                 xim_best_allowed_style |= GdkIMPreeditPosition;
-                 if (!(style & GdkIMPreeditPosition))
-                   xim_best_allowed_style |= GdkIMPreeditCallbacks;
+                 xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION;
+                 if (!(style & GDK_IM_PREEDIT_POSITION))
+                   xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS;
                }
            }
        }
     }
-  if (style & GdkIMStatusMask)
+  if (style & GDK_IM_STATUS_MASK)
     {
-      xim_best_allowed_style &= ~GdkIMStatusMask;
-      
-      xim_best_allowed_style |= GdkIMStatusNone;
-      if (!(style & GdkIMStatusNone))
+      xim_best_allowed_style &= ~GDK_IM_STATUS_MASK;
+
+      xim_best_allowed_style |= GDK_IM_STATUS_NONE;
+      if (!(style & GDK_IM_STATUS_NONE))
        {
-         xim_best_allowed_style |= GdkIMStatusNothing;
-         if (!(style & GdkIMStatusNothing))
+         xim_best_allowed_style |= GDK_IM_STATUS_NOTHING;
+         if (!(style & GDK_IM_STATUS_NOTHING))
            {
-             xim_best_allowed_style |= GdkIMStatusArea;
-             if (!(style & GdkIMStatusArea))
-               xim_best_allowed_style |= GdkIMStatusCallbacks;
+             xim_best_allowed_style |= GDK_IM_STATUS_AREA;
+             if (!(style & GDK_IM_STATUS_AREA))
+               xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS;
            }
        }
     }
@@ -3960,13 +3960,13 @@ gdk_im_end (void)
 GdkIMStyle
 gdk_im_decide_style (GdkIMStyle supported_style)
 {
-  return GdkIMPreeditNone | GdkIMStatusNone;
+  return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
 }
 
 GdkIMStyle
 gdk_im_set_best_style (GdkIMStyle style)
 {
-  return GdkIMPreeditNone | GdkIMStatusNone;
+  return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
 }
 
 gint 
@@ -3991,7 +3991,7 @@ gdk_ic_destroy (GdkIC ic)
 GdkIMStyle
 gdk_ic_get_style (GdkIC ic)
 {
-  return GdkIMPreeditNone | GdkIMStatusNone;
+  return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
 }
 
 void 
index 313270024044de9b4cbcc5a841a836ee9879c307..cf4babbcb75b33a81bd7a3478f1902be8d444d6b 100644 (file)
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -307,6 +307,11 @@ void             gdk_window_set_functions   (GdkWindow       *window,
                                          GdkWMFunction    functions);
 GList *       gdk_window_get_toplevels   (void);
 
+void          gdk_drawable_set_data      (GdkDrawable     *drawable,
+                                         const gchar     *key,
+                                         gpointer         data,
+                                         GDestroyNotify   destroy_func);
+                                         
 
 /* Cursors
  */
@@ -455,6 +460,22 @@ gint            gdk_colormap_get_system_size  (void);
 
 void gdk_colormap_change (GdkColormap  *colormap,
                          gint           ncolors);
+
+
+gint  gdk_colormap_alloc_colors   (GdkColormap *colormap,
+                                  GdkColor    *colors,
+                                  gint         ncolors,
+                                  gboolean     writeable,
+                                  gboolean     best_match,
+                                  gboolean    *success);
+gboolean gdk_colormap_alloc_color (GdkColormap *colormap,
+                                  GdkColor    *color,
+                                  gboolean     writeable,
+                                  gboolean     best_match);
+void     gdk_colormap_free_colors (GdkColormap *colormap,
+                                  GdkColor    *colors,
+                                  gint         ncolors);
+     
 void gdk_colors_store   (GdkColormap   *colormap,
                          GdkColor      *colors,
                          gint           ncolors);
@@ -482,8 +503,10 @@ gint gdk_color_alloc        (GdkColormap   *colormap,
                          GdkColor      *color);
 gint gdk_color_change   (GdkColormap   *colormap,
                          GdkColor      *color);
-gint gdk_color_equal    (GdkColor      *colora,
-                         GdkColor      *colorb);
+guint gdk_color_hash     (const GdkColor *colora,
+                         const GdkColor *colorb);
+gint gdk_color_equal    (const GdkColor *colora,
+                         const GdkColor *colorb);
 
 
 /* Fonts
@@ -722,22 +745,27 @@ GdkTimeCoord *gdk_input_motion_events (GdkWindow *window,
 /* International Input Method Support Functions
  */
 
-gint   gdk_im_ready            (void);
-
-void   gdk_im_begin            (GdkIC ic, GdkWindow* window);
-void   gdk_im_end              (void);
-GdkIMStyle gdk_im_decide_style (GdkIMStyle supported_style);
-GdkIMStyle gdk_im_set_best_style (GdkIMStyle best_allowed_style);
-GdkIC  gdk_ic_new              (GdkWindow* client_window,
-                                GdkWindow* focus_window,
-                                GdkIMStyle style, ...);
-void   gdk_ic_destroy          (GdkIC ic);
-GdkIMStyle   gdk_ic_get_style  (GdkIC ic);
-void   gdk_ic_set_values       (GdkIC ic, ...);
-void   gdk_ic_get_values       (GdkIC ic, ...);
-void   gdk_ic_set_attr         (GdkIC ic, const char *target, ...);
-void   gdk_ic_get_attr         (GdkIC ic, const char *target, ...);
-GdkEventMask gdk_ic_get_events (GdkIC ic);
+gint         gdk_im_ready         (void);
+
+void         gdk_im_begin         (GdkIC      ic, 
+                                   GdkWindow* window);
+void         gdk_im_end                   (void);
+GdkIMStyle   gdk_im_decide_style   (GdkIMStyle supported_style);
+GdkIMStyle   gdk_im_set_best_style (GdkIMStyle best_allowed_style);
+GdkIC        gdk_ic_new                   (GdkWindow* client_window,
+                                   GdkWindow* focus_window,
+                                   GdkIMStyle style, ...);
+void         gdk_ic_destroy       (GdkIC      ic);
+GdkIMStyle   gdk_ic_get_style     (GdkIC      ic);
+void         gdk_ic_set_values    (GdkIC      ic,  
+                                   ...);
+void         gdk_ic_get_values    (GdkIC      ic, 
+                                   ...);
+void         gdk_ic_set_attr      (GdkIC      ic, 
+                                   const char *target, ...);
+void         gdk_ic_get_attr      (GdkIC       ic, 
+                                   const char *target, ...);
+GdkEventMask gdk_ic_get_events    (GdkIC       ic);
 
 /* Color Context */
 
@@ -857,6 +885,7 @@ guint    gdk_keyval_to_lower                  (guint        keyval);
 gboolean gdk_keyval_is_upper             (guint        keyval);
 gboolean gdk_keyval_is_lower             (guint        keyval);
 
+
 #include <gdk/gdkrgb.h>
 
 #ifdef __cplusplus
index b17e26a1c5733d1567c4e0536a407a8dc6499e7d..fa810473e60b4df11088435f46795581302904b7 100644 (file)
@@ -16,6 +16,7 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+#include <time.h>
 #include <X11/Xlib.h>
 #include "gdk.h"
 #include "gdkprivate.h"
@@ -52,8 +53,12 @@ gdk_colormap_new (GdkVisual *visual,
 
   private->xdisplay = gdk_display;
   private->visual = visual;
-  private->next_color = 0;
   private->ref_count = 1;
+
+  private->hash = NULL;
+  private->last_sync_time = 0;
+  private->info = NULL;
+  
   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
 
   colormap->size = visual->colormap_size;
@@ -63,6 +68,12 @@ gdk_colormap_new (GdkVisual *visual,
     {
     case GDK_VISUAL_GRAYSCALE:
     case GDK_VISUAL_PSEUDO_COLOR:
+      private->info = g_new0 (GdkColorInfo, colormap->size);
+      colormap->colors = g_new (GdkColor, colormap->size);
+      
+      private->hash = g_hash_table_new (gdk_color_hash,
+                                       gdk_color_equal);
+      
       private->private_val = private_cmap;
       private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
                                            xvisual, (private_cmap) ? (AllocAll) : (AllocNone));
@@ -134,12 +145,15 @@ gdk_colormap_real_destroy (GdkColormap *colormap)
   GdkColormapPrivate *private = (GdkColormapPrivate*) colormap;
 
   g_return_if_fail (colormap != NULL);
-
-  if (private->ref_count > 0)
-    return;
+  g_return_if_fail (private->ref_count > 0);
 
   gdk_colormap_remove (colormap);
   XFreeColormap (private->xdisplay, private->xcolormap);
+
+  if (private->hash)
+    g_hash_table_destroy (private->hash);
+  
+  g_free (private->info);
   g_free (colormap->colors);
   g_free (colormap);
 }
@@ -165,13 +179,61 @@ gdk_colormap_unref (GdkColormap *cmap)
     gdk_colormap_real_destroy (cmap);
 }
 
+#define MIN_SYNC_TIME 2
+
+void
+gdk_colormap_sync (GdkColormap *colormap,
+                  gboolean     force)
+{
+  time_t current_time;
+  GdkColormapPrivate *private = (GdkColormapPrivate *)colormap;
+  XColor *xpalette;
+  gint nlookup;
+  gint i;
+  
+  g_return_if_fail (colormap != NULL);
+
+  current_time = time (NULL);
+  if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME))
+    return;
+
+  private->last_sync_time = current_time;
+
+  nlookup = 0;
+  xpalette = g_new (XColor, colormap->size);
+  
+  for (i = 0; i < colormap->size; i++)
+    {
+      if (private->info[i].ref_count == 0)
+       {
+         xpalette[nlookup].pixel = i;
+         xpalette[nlookup].red = 0;
+         xpalette[nlookup].green = 0;
+         xpalette[nlookup].blue = 0;
+         nlookup++;
+       }
+    }
+  
+  XQueryColors (gdk_display, private->xcolormap, xpalette, nlookup);
+  
+  for (i = 0; i < nlookup; i++)
+    {
+      gulong pixel = xpalette[i].pixel;
+      colormap->colors[pixel].pixel = pixel;
+      colormap->colors[pixel].red = xpalette[i].red;
+      colormap->colors[pixel].green = xpalette[i].green;
+      colormap->colors[pixel].blue = xpalette[i].blue;
+    }
+  
+  g_free (xpalette);
+}
+                  
+
 GdkColormap*
 gdk_colormap_get_system (void)
 {
   static GdkColormap *colormap = NULL;
   GdkColormapPrivate *private;
-  XColor *xpalette;
-  gint i;
 
   if (!colormap)
     {
@@ -182,37 +244,25 @@ gdk_colormap_get_system (void)
       private->xcolormap = DefaultColormap (gdk_display, gdk_screen);
       private->visual = gdk_visual_get_system ();
       private->private_val = FALSE;
-      private->next_color = 0;
       private->ref_count = 1;
 
+      private->hash = NULL;
+      private->last_sync_time = 0;
+      private->info = NULL;
+
+      colormap->colors = NULL;
       colormap->size = private->visual->colormap_size;
-      colormap->colors = g_new (GdkColor, colormap->size);
 
       if ((private->visual->type == GDK_VISUAL_GRAYSCALE) ||
          (private->visual->type == GDK_VISUAL_PSEUDO_COLOR))
        {
-         xpalette = g_new (XColor, colormap->size);
+         private->info = g_new0 (GdkColorInfo, colormap->size);
+         colormap->colors = g_new (GdkColor, colormap->size);
          
-         for (i = 0; i < colormap->size; i++)
-           {
-             xpalette[i].pixel = i;
-             xpalette[i].red = 0;
-             xpalette[i].green = 0;
-             xpalette[i].blue = 0;
-           }
-         
-         XQueryColors (gdk_display, private->xcolormap, xpalette, 
-                       colormap->size);
-         
-         for (i = 0; i < colormap->size; i++)
-           {
-             colormap->colors[i].pixel = xpalette[i].pixel;
-             colormap->colors[i].red = xpalette[i].red;
-             colormap->colors[i].green = xpalette[i].green;
-             colormap->colors[i].blue = xpalette[i].blue;
-           }
+         private->hash = g_hash_table_new (gdk_color_hash,
+                                           gdk_color_equal);
 
-         g_free (xpalette);
+         gdk_colormap_sync (colormap, TRUE);
        }
 
       gdk_colormap_add (colormap);
@@ -258,7 +308,6 @@ gdk_colormap_change (GdkColormap *colormap,
        }
 
       XStoreColors (private->xdisplay, private->xcolormap, palette, ncolors);
-      private->next_color = MAX (private->next_color, ncolors);
       break;
 
     case GDK_VISUAL_DIRECT_COLOR:
@@ -339,6 +388,7 @@ gdk_colors_alloc (GdkColormap   *colormap,
 {
   GdkColormapPrivate *private;
   gint return_val;
+  gint i;
 
   g_return_val_if_fail (colormap != NULL, 0);
 
@@ -347,23 +397,65 @@ gdk_colors_alloc (GdkColormap   *colormap,
   return_val = XAllocColorCells (private->xdisplay, private->xcolormap,
                                 contiguous, planes, nplanes, pixels, npixels);
 
+  if (return_val)
+    {
+      for (i=0; i<npixels; i++)
+       {
+         private->info[pixels[i]].ref_count++;
+         private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
+       }
+    }
+
   return return_val;
 }
 
+/* This is almost identical to gdk_colormap_free_colors.
+ * Keep them in sync!
+ */
 void
 gdk_colors_free (GdkColormap *colormap,
-                gulong      *pixels,
-                gint         npixels,
+                gulong      *in_pixels,
+                gint         in_npixels,
                 gulong       planes)
 {
   GdkColormapPrivate *private;
+  gulong *pixels;
+  gint npixels = 0;
+  gint i;
 
   g_return_if_fail (colormap != NULL);
+  g_return_if_fail (in_pixels != NULL);
 
   private = (GdkColormapPrivate*) colormap;
 
-  XFreeColors (private->xdisplay, private->xcolormap,
-              pixels, npixels, planes);
+  if ((private->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
+      (private->visual->type != GDK_VISUAL_GRAYSCALE))
+    return;
+  
+  pixels = g_new (gulong, in_npixels);
+
+  for (i=0; i<in_npixels; i++)
+    {
+      gulong pixel = in_pixels[i];
+      
+      if (private->info[pixel].ref_count)
+       {
+         private->info[pixel].ref_count--;
+
+         if (private->info[pixel].ref_count == 0)
+           {
+             pixels[npixels++] = pixel;
+             if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
+               g_hash_table_remove (private->hash, &colormap->colors[in_pixels[i]]);
+             private->info[pixel].flags = 0;
+           }
+       }
+    }
+
+  if (npixels)
+    XFreeColors (private->xdisplay, private->xcolormap,
+                pixels, npixels, planes);
+  g_free (pixels);
 }
 
 /*
@@ -494,19 +586,22 @@ gdk_color_parse (const gchar *spec,
   return return_val;
 }
 
-gboolean
-gdk_color_alloc (GdkColormap *colormap,
-                GdkColor    *color)
+/********************
+ * Color allocation *
+ ********************/
+
+/* Try to allocate a single color using XAllocColor. If it succeeds,
+ * cache the result in our colormap, and store in ret.
+ */
+static gboolean 
+gdk_colormap_alloc1 (GdkColormap *colormap,
+                    GdkColor    *color,
+                    GdkColor    *ret)
 {
   GdkColormapPrivate *private;
-  GdkVisual *visual;
   XColor xcolor;
-  gchar *available = NULL;
-  gboolean return_val;
-  gint i, index;
 
-  g_return_val_if_fail (colormap != NULL, FALSE);
-  g_return_val_if_fail (color != NULL, FALSE);
+  private = (GdkColormapPrivate*) colormap;
 
   xcolor.red = color->red;
   xcolor.green = color->green;
@@ -514,113 +609,458 @@ gdk_color_alloc (GdkColormap *colormap,
   xcolor.pixel = color->pixel;
   xcolor.flags = DoRed | DoGreen | DoBlue;
 
-  return_val = FALSE;
+  if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+    {
+      ret->pixel = xcolor.pixel;
+      ret->red = xcolor.red;
+      ret->green = xcolor.green;
+      ret->blue = xcolor.blue;
+      
+      if (ret->pixel < colormap->size)
+       {
+         if (private->info[ret->pixel].ref_count) /* got a duplicate */
+           {
+             XFreeColors (private->xdisplay, private->xcolormap,
+                          &ret->pixel, 1, 0);
+           }
+         else
+           {
+             colormap->colors[ret->pixel] = *color;
+             private->info[ret->pixel].ref_count = 1;
+
+             g_hash_table_insert (private->hash,
+                                  &colormap->colors[ret->pixel],
+                                  &colormap->colors[ret->pixel]);
+           }
+       }
+      return TRUE;
+    }
+  else
+    {
+      return FALSE;
+    }
+}
+
+static gint
+gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
+                                    GdkColor    *colors,
+                                    gint         ncolors,
+                                    gboolean     writeable,
+                                    gboolean     best_match,
+                                    gboolean    *success)
+{
+  GdkColormapPrivate *private;
+  gulong *pixels;
+  Status status;
+  gint i, index;
+
   private = (GdkColormapPrivate*) colormap;
 
-  switch (private->visual->type)
+  if (private->private_val)
     {
-    case GDK_VISUAL_GRAYSCALE:
-    case GDK_VISUAL_PSEUDO_COLOR:
-      if (private->private_val)
+      index = 0;
+      for (i=0; i<ncolors; i++)
        {
-         if (private->next_color >= colormap->size)
+         while ((index < colormap->size) && (private->info[index].ref_count != 0))
+           index++;
+         
+         if (index < colormap->size)
            {
-             available = g_new (gchar, colormap->size);
-             for (i = 0; i < colormap->size; i++)
-               available[i] = TRUE;
-
-             index = gdk_colormap_match_color (colormap, color, available);
-             if (index != -1)
-               {
-                 available[index] = FALSE;
-                 *color = colormap->colors[index];
-                 return_val = TRUE;
-               }
-             else
-               {
-                 return_val = FALSE;
-               }
+             colors[i].pixel = index;
+             success[i] = TRUE;
+             private->info[index].ref_count++;
+             private->info[i].flags |= GDK_COLOR_WRITEABLE;
            }
          else
+           break;
+       }
+      return i;
+    }
+  else
+    {
+      pixels = g_new (gulong, ncolors);
+      /* Allocation of a writeable color cells */
+      
+      status =  XAllocColorCells (private->xdisplay, private->xcolormap,
+                                 FALSE, NULL, 0, pixels, ncolors);
+      if (status)
+       {
+         for (i=0; i<ncolors; i++)
            {
-             xcolor.pixel = colormap->size - 1 -private->next_color;
-             color->pixel = xcolor.pixel;
-             private->next_color += 1;
+             colors[i].pixel = pixels[i];
+             private->info[pixels[i]].ref_count++;
+             private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
+           }
+       }
+      
+      g_free (pixels);
 
-             XStoreColor (private->xdisplay, private->xcolormap, &xcolor);
-             return_val = TRUE;
+      return status ? ncolors : 0; 
+    }
+}
+
+static gint
+gdk_colormap_alloc_colors_private (GdkColormap *colormap,
+                                  GdkColor    *colors,
+                                  gint         ncolors,
+                                  gboolean     writeable,
+                                  gboolean     best_match,
+                                  gboolean    *success)
+{
+  GdkColormapPrivate *private;
+  gint i, index;
+  XColor *store = g_new (XColor, ncolors);
+  gint nstore = 0;
+  gint nremaining = 0;
+  
+  private = (GdkColormapPrivate*) colormap;
+  index = -1;
+
+  /* First, store the colors we have room for */
+
+  index = 0;
+  for (i=0; i<ncolors; i++)
+    {
+      if (!success[i])
+       {
+         while ((index < colormap->size) && (private->info[index].ref_count != 0))
+           index++;
+
+         if (index < colormap->size)
+           {
+             store[nstore].red = colors[i].red;
+             store[nstore].blue = colors[i].blue;
+             store[nstore].green = colors[i].green;
+             store[nstore].pixel = index;
+             nstore++;
+
+             success[i] = TRUE;
+
+             colors[i].pixel = index;
+             private->info[index].ref_count++;
            }
+         else
+           nremaining++;
        }
-      else
+    }
+  
+  XStoreColors (private->xdisplay, private->xcolormap, store, nstore);
+  g_free (store);
+
+  if (nremaining > 0 && best_match)
+    {
+      /* Get best matches for remaining colors */
+
+      gchar *available = g_new (gchar, colormap->size);
+      for (i = 0; i < colormap->size; i++)
+       available[i] = TRUE;
+
+      for (i=0; i<ncolors; i++)
        {
-         while (1)
+         if (!success[i])
            {
-             if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+             index = gdk_colormap_match_color (colormap, 
+                                               &colors[i], 
+                                               available);
+             if (index != -1)
                {
-                 color->pixel = xcolor.pixel;
-                 color->red = xcolor.red;
-                 color->green = xcolor.green;
-                 color->blue = xcolor.blue;
-
-                 if (color->pixel < colormap->size)
-                   colormap->colors[color->pixel] = *color;
+                 colors[i] = colormap->colors[index];
+                 private->info[index].ref_count++;
 
-                 return_val = TRUE;
-                 break;
+                 success[i] = TRUE;
+                 nremaining--;
                }
-             else
-               {
-                 if (available == NULL)
-                   {
-                     available = g_new (gchar, colormap->size);
-                     for (i = 0; i < colormap->size; i++)
-                       available[i] = TRUE;
-                   }
+           }
+       }
+      g_free (available);
+    }
+
+  return (ncolors - nremaining);
+}
+
+static gint
+gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
+                                 GdkColor    *colors,
+                                 gint         ncolors,
+                                 gboolean     writeable,
+                                 gboolean     best_match,
+                                 gboolean    *success)
+{
+  GdkColormapPrivate *private;
+  gint i, index;
+  gint nremaining = 0;
+  gint nfailed = 0;
+
+  private = (GdkColormapPrivate*) colormap;
+  index = -1;
+
+  for (i=0; i<ncolors; i++)
+    {
+      if (!success[i])
+       {
+         if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
+           success[i] = TRUE;
+         else
+           nremaining++;
+       }
+    }
+
 
-                 index = gdk_colormap_match_color (colormap, color, available);
+  if (nremaining > 0 && best_match)
+    {
+      gchar *available = g_new (gchar, colormap->size);
+      for (i = 0; i < colormap->size; i++)
+       available[i] = ((private->info[i].ref_count == 0) ||
+                       !(private->info[i].flags && GDK_COLOR_WRITEABLE));
+      gdk_colormap_sync (colormap, FALSE);
+      
+      while (nremaining > 0)
+       {
+         for (i=0; i<ncolors; i++)
+           {
+             if (!success[i])
+               {
+                 index = gdk_colormap_match_color (colormap, &colors[i], available);
                  if (index != -1)
                    {
-                     available[index] = FALSE;
-                     xcolor.red = colormap->colors[index].red;
-                     xcolor.green = colormap->colors[index].green;
-                     xcolor.blue = colormap->colors[index].blue;
+                     if (private->info[index].ref_count)
+                       {
+                         private->info[index].ref_count++;
+                         colors[i] = colormap->colors[index];
+                         success[i] = TRUE;
+                         nremaining--;
+                       }
+                     else
+                       {
+                         if (gdk_colormap_alloc1 (colormap, 
+                                                  &colormap->colors[index],
+                                                  &colors[i]))
+                           {
+                             success[i] = TRUE;
+                             nremaining--;
+                             break;
+                           }
+                         else
+                           {
+                             available[index] = FALSE;
+                           }
+                       }
                    }
                  else
                    {
-                     return_val = FALSE;
-                     break;
+                     nfailed++;
+                     nremaining--;
+                     success[i] = 2; /* flag as permanent failure */
                    }
                }
            }
        }
+      g_free (available);
+    }
+
+  /* Change back the values we flagged as permanent failures */
+  if (nfailed > 0)
+    {
+      for (i=0; i<ncolors; i++)
+       if (success[i] == 2)
+         success[i] = FALSE;
+      nremaining = nfailed;
+    }
+  
+  return (ncolors - nremaining);
+}
+
+static gint
+gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
+                                      GdkColor    *colors,
+                                      gint         ncolors,
+                                      gboolean     writeable,
+                                      gboolean     best_match,
+                                      gboolean    *success)
+{
+  GdkColormapPrivate *private;
+  GdkColor *lookup_color;
+  gint i;
+  gint nremaining = 0;
+
+  private = (GdkColormapPrivate*) colormap;
+
+  /* Check for an exact match among previously allocated colors */
+
+  for (i=0; i<ncolors; i++)
+    {
+      if (!success[i])
+       {
+         lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
+         if (lookup_color)
+           {
+             private->info[lookup_color->pixel].ref_count++;
+             colors[i].pixel = lookup_color->pixel;
+             success[i] = TRUE;
+           }
+         else
+           nremaining++;
+       }
+    }
+
+  /* If that failed, we try to allocate a new color, or approxmiate
+   * with what we can get if best_match is TRUE.
+   */
+  if (nremaining > 0)
+    {
+      if (private->private_val)
+       return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
+      else
+       return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
+    }
+  else
+    return 0;
+}
+
+gint
+gdk_colormap_alloc_colors (GdkColormap *colormap,
+                          GdkColor    *colors,
+                          gint         ncolors,
+                          gboolean     writeable,
+                          gboolean     best_match,
+                          gboolean    *success)
+{
+  GdkColormapPrivate *private;
+  GdkVisual *visual;
+  gint i;
+  gint nremaining = 0;
+  XColor xcolor;
+
+  g_return_val_if_fail (colormap != NULL, FALSE);
+  g_return_val_if_fail (colors != NULL, FALSE);
+
+  private = (GdkColormapPrivate*) colormap;
+
+  for (i=0; i<ncolors; i++)
+    {
+      success[i] = FALSE;
+    }
+
+  switch (private->visual->type)
+    {
+    case GDK_VISUAL_PSEUDO_COLOR:
+    case GDK_VISUAL_GRAYSCALE:
+      if (writeable)
+       return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
+                                                   writeable, best_match, success);
+      else
+       return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
+                                                   writeable, best_match, success);
       break;
 
     case GDK_VISUAL_DIRECT_COLOR:
+    case GDK_VISUAL_TRUE_COLOR:
       visual = private->visual;
-      xcolor.pixel = (((xcolor.red >> (16 - visual->red_prec)) << visual->red_shift) +
-                     ((xcolor.green >> (16 - visual->green_prec)) << visual->green_shift) +
-                     ((xcolor.blue >> (16 - visual->blue_prec)) << visual->blue_shift));
-      color->pixel = xcolor.pixel;
-      return_val = TRUE;
+
+      for (i=0; i<ncolors; i++)
+       {
+         colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
+                            ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
+                            ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
+         success[i] = TRUE;
+       }
       break;
 
     case GDK_VISUAL_STATIC_GRAY:
     case GDK_VISUAL_STATIC_COLOR:
-    case GDK_VISUAL_TRUE_COLOR:
-      if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+      for (i=0; i<ncolors; i++)
        {
-         color->pixel = xcolor.pixel;
-         return_val = TRUE;
+         xcolor.red = colors[i].red;
+         xcolor.green = colors[i].green;
+         xcolor.blue = colors[i].blue;
+         xcolor.pixel = colors[i].pixel;
+         xcolor.flags = DoRed | DoGreen | DoBlue;
+
+         if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+           {
+             colors[i].pixel = xcolor.pixel;
+             success[i] = TRUE;
+           }
+         else
+           nremaining++;
        }
-      else
-       return_val = FALSE;
       break;
     }
+  return nremaining;
+}
 
-  if (available)
-    g_free (available);
-  
-  return return_val;
+gboolean
+gdk_colormap_alloc_color (GdkColormap *colormap,
+                         GdkColor    *color,
+                         gboolean     writeable,
+                         gboolean     best_match)
+{
+  gboolean success;
+
+  gdk_colormap_alloc_colors (colormap, color, 1, writeable, best_match,
+                            &success);
+
+  return success;
+}
+
+/* This is almost identical to gdk_colors_free.
+ * Keep them in sync!
+ */
+void
+gdk_colormap_free_colors (GdkColormap *colormap,
+                         GdkColor    *colors,
+                         gint         ncolors)
+{
+  GdkColormapPrivate *private;
+  gulong *pixels;
+  gint npixels = 0;
+  gint i;
+
+  g_return_if_fail (colormap != NULL);
+  g_return_if_fail (colors != NULL);
+
+  private = (GdkColormapPrivate*) colormap;
+
+  if ((private->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
+      (private->visual->type != GDK_VISUAL_GRAYSCALE))
+    return;
+
+  pixels = g_new (gulong, ncolors);
+
+  for (i=0; i<ncolors; i++)
+    {
+      gulong pixel = colors[i].pixel;
+      
+      if (private->info[pixel].ref_count)
+       {
+         private->info[pixel].ref_count--;
+
+         if (private->info[pixel].ref_count == 0)
+           {
+             pixels[npixels++] = pixel;
+             if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
+               g_hash_table_remove (private->hash, &colors[i]);
+             private->info[pixel].flags = 0;
+           }
+       }
+    }
+
+  if (npixels)
+    XFreeColors (private->xdisplay, private->xcolormap,
+                pixels, npixels, 0);
+
+  g_free (pixels);
+}
+
+gboolean
+gdk_color_alloc (GdkColormap *colormap,
+                GdkColor    *color)
+{
+  gboolean success;
+
+  gdk_colormap_alloc_colors (colormap, color, 1, FALSE, TRUE, &success);
+
+  return success;
 }
 
 gboolean
@@ -645,9 +1085,19 @@ gdk_color_change (GdkColormap *colormap,
   return TRUE;
 }
 
+guint
+gdk_color_hash (const GdkColor *colora,
+               const GdkColor *colorb)
+{
+  return ((colora->red) +
+         (colora->green << 11) +
+         (colora->blue << 22) +
+         (colora->blue >> 6));
+}
+
 gint
-gdk_color_equal (GdkColor *colora,
-                GdkColor *colorb)
+gdk_color_equal (const GdkColor *colora,
+                const GdkColor *colorb)
 {
   g_return_val_if_fail (colora != NULL, FALSE);
   g_return_val_if_fail (colorb != NULL, FALSE);
@@ -657,6 +1107,9 @@ gdk_color_equal (GdkColor *colora,
          (colora->blue == colorb->blue));
 }
 
+/* XXX: Do not use this function until it is fixed. An X Colormap
+ *      is useless unless we also have the visual.
+ */
 GdkColormap*
 gdkx_colormap_get (Colormap xcolormap)
 {
@@ -677,7 +1130,6 @@ gdkx_colormap_get (Colormap xcolormap)
   private->xcolormap = xcolormap;
   private->visual = NULL;
   private->private_val = TRUE;
-  private->next_color = 0;
 
   /* To do the following safely, we would have to have some way of finding
    * out what the size or visual of the given colormap is. It seems
index 9fdef0ffcceb18e602c70710df860275d67fcfe3..dfaf4822c94c35b70d00e504c54a98849036c180 100644 (file)
@@ -34,6 +34,13 @@ typedef struct
   gint transparent;
 } _GdkPixmapColor;
 
+typedef struct
+{
+  guint ncolors;
+  GdkColormap *colormap;
+  gulong pixels[1];
+} _GdkPixmapInfo;
+
 GdkPixmap*
 gdk_pixmap_new (GdkWindow *window,
                gint       width,
@@ -388,13 +395,6 @@ gdk_pixmap_extract_color (gchar *buffer)
   return retcol;
 }
 
-static void
-free_color (gpointer key, gpointer value, gpointer user_data)
-{
-  g_free (key);
-  g_free (value);
-}
-  
 
 enum buffer_op
 {
@@ -403,6 +403,23 @@ enum buffer_op
   op_body
 };
   
+
+static void 
+gdk_xpm_destroy_notify (gpointer data)
+{
+  _GdkPixmapInfo *info = (_GdkPixmapInfo *)data;
+  GdkColor color;
+  int i;
+
+  for (i=0; i<info->ncolors; i++)
+    {
+      color.pixel = info->pixels[i];
+      gdk_colormap_free_colors (info->colormap, &color, 1);
+    }
+
+  gdk_colormap_unref (info->colormap);
+  g_free (info);
+}
   
 static GdkPixmap *
 _gdk_pixmap_create_from_xpm (GdkWindow  *window,
@@ -420,9 +437,12 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
   GdkColor tmp_color;
   gint width, height, num_cols, cpp, n, ns, cnt, xcnt, ycnt, wbytes;
   gchar *buffer, pixel_str[32];
+  gchar *name_buf;
   _GdkPixmapColor *color = NULL, *fallbackcolor = NULL;
+  _GdkPixmapColor *colors = NULL;
   gulong index;
-  GHashTable *colors = NULL;
+  GHashTable *color_hash = NULL;
+  _GdkPixmapInfo *color_info = NULL;
   
   if ((window == NULL) && (colormap == NULL))
     g_warning ("Creating pixmap from xpm with NULL window and colormap");
@@ -449,14 +469,30 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
       return NULL;
     }
   
-  colors = g_hash_table_new (g_str_hash, g_str_equal);
+  color_hash = g_hash_table_new (g_str_hash, g_str_equal);
   
   if (transparent_color == NULL)
     {
       gdk_color_white (colormap, &tmp_color);
       transparent_color = &tmp_color;
     }
-  
+
+  /* For pseudo-color and grayscale visuals, we have to remember
+   * the colors we allocated, so we can free them later.
+   */
+  if ((visual->type == GDK_VISUAL_PSEUDO_COLOR) ||
+      (visual->type == GDK_VISUAL_GRAYSCALE))
+    {
+      color_info = g_malloc (sizeof (_GdkPixmapInfo) + 
+                            sizeof(gulong) * (num_cols - 1));
+      color_info->ncolors = num_cols;
+      color_info->colormap = colormap;
+      gdk_colormap_ref (colormap);
+    }
+
+  name_buf = g_new (gchar, num_cols * (cpp+1));
+  colors = g_new (_GdkPixmapColor, num_cols);
+
   for (cnt = 0; cnt < num_cols; cnt++)
     {
       gchar *color_name;
@@ -465,8 +501,8 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
       if (buffer == NULL)
        goto error;
       
-      color = g_new (_GdkPixmapColor, 1);
-      color->color_string = g_new (gchar, cpp + 1);
+      color = &colors[cnt];
+      color->color_string = &name_buf [cnt * (cpp + 1)];
       strncpy (color->color_string, buffer, cpp);
       color->color_string[cpp] = 0;
       buffer += strlen (color->color_string);
@@ -486,7 +522,11 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
       /* FIXME: The remaining slowness appears to happen in this
          function. */
       gdk_color_alloc (colormap, &color->color);
-      g_hash_table_insert (colors, color->color_string, color);
+
+      if (color_info)
+       color_info->pixels[cnt] = color->color.pixel;
+      
+      g_hash_table_insert (color_hash, color->color_string, color);
       if (cnt == 0)
        fallbackcolor = color;
     }
@@ -531,7 +571,7 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
          pixel_str[cpp] = 0;
          ns = 0;
          
-         color = g_hash_table_lookup (colors, pixel_str);
+         color = g_hash_table_lookup (color_hash, pixel_str);
          
          if (!color) /* screwed up XPM file */
            color = fallbackcolor;
@@ -558,6 +598,10 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
   if (image != NULL)
     {
       pixmap = gdk_pixmap_new (window, width, height, visual->depth);
+
+      if (color_info)
+       gdk_drawable_set_data (pixmap, "gdk-xpm", color_info, 
+                              gdk_xpm_destroy_notify);
       
       gc = gdk_gc_new (pixmap);
       gdk_gc_set_foreground (gc, transparent_color);
@@ -565,13 +609,18 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
       gdk_gc_destroy (gc);
       gdk_image_destroy (image);
     }
+  else if (color_info)
+    gdk_xpm_destroy_notify (color_info);
   
+  if (color_hash != NULL)
+    g_hash_table_destroy (color_hash);
+
   if (colors != NULL)
-    {
-      g_hash_table_foreach (colors, free_color, 0);
-      g_hash_table_destroy (colors);
-    }
-  
+    g_free (colors);
+
+  if (name_buf != NULL)
+    g_free (name_buf);
+
   return pixmap;
 }
 
@@ -720,6 +769,7 @@ gdk_pixmap_unref (GdkPixmap *pixmap)
     {
       XFreePixmap (private->xdisplay, private->xwindow);
       gdk_xid_table_remove (private->xwindow);
+      g_dataset_destroy (private);
       g_free (private);
     }
 }
index 6e9889c3e4905535e8f1514aba10e6e7b8ed7384..9ed85a4663ba7153e77c9f7ef107906f85a5f96d 100644 (file)
@@ -41,6 +41,7 @@ typedef struct _GdkWindowPrivate       GdkPixmapPrivate;
 typedef struct _GdkImagePrivate               GdkImagePrivate;
 typedef struct _GdkGCPrivate          GdkGCPrivate;
 typedef struct _GdkColormapPrivate     GdkColormapPrivate;
+typedef struct _GdkColorInfo           GdkColorInfo;
 typedef struct _GdkVisualPrivate       GdkVisualPrivate;
 typedef struct _GdkFontPrivate        GdkFontPrivate;
 typedef struct _GdkCursorPrivate       GdkCursorPrivate;
@@ -111,6 +112,16 @@ struct _GdkGCPrivate
   guint ref_count;
 };
 
+typedef enum {
+  GDK_COLOR_WRITEABLE = 1 << 0
+} GdkColorInfoFlags;
+
+struct _GdkColorInfo
+{
+  GdkColorInfoFlags flags;
+  guint ref_count;
+};
+
 struct _GdkColormapPrivate
 {
   GdkColormap colormap;
@@ -118,7 +129,11 @@ struct _GdkColormapPrivate
   Display *xdisplay;
   GdkVisual *visual;
   gint private_val;
-  gint next_color;
+
+  GHashTable *hash;
+  GdkColorInfo *info;
+  time_t last_sync_time;
+  
   guint ref_count;
 };
 
index 5ec44c2d4a0a36fb3dbb2841b66a498f80b6c8ac..67f9fb3533f7360196b8390150b1e8b4b8b3781e 100644 (file)
@@ -618,15 +618,18 @@ typedef enum
 
 typedef enum                   /*< flags >*/
 {
-  GdkIMPreeditArea     = 0x0001L, /*< nick=preedit-area >*/
-  GdkIMPreeditCallbacks = 0x0002L, /*< nick=preedit-callbacks >*/
-  GdkIMPreeditPosition = 0x0004L, /*< nick=preedit-position >*/
-  GdkIMPreeditNothing  = 0x0008L, /*< nick=preedit-nothing >*/
-  GdkIMPreeditNone     = 0x0010L, /*< nick=preedit-none >*/
-  GdkIMStatusArea      = 0x0100L, /*< nick=status-area >*/
-  GdkIMStatusCallbacks = 0x0200L, /*< nick=status-callbacks >*/
-  GdkIMStatusNothing   = 0x0400L, /*< nick=status-nothing >*/
-  GdkIMStatusNone      = 0x0800L  /*< nick=status-none >*/
+  GDK_IM_PREEDIT_AREA     = 0x0001, 
+  GDK_IM_PREEDIT_CALLBACKS = 0x0002, 
+  GDK_IM_PREEDIT_POSITION  = 0x0004,
+  GDK_IM_PREEDIT_NOTHING   = 0x0008,
+  GDK_IM_PREEDIT_NONE     = 0x0010,
+  GDK_IM_PREEDIT_MASK      = 0x001f,
+
+  GDK_IM_STATUS_AREA      = 0x0100, 
+  GDK_IM_STATUS_CALLBACKS  = 0x0200,
+  GDK_IM_STATUS_NOTHING           = 0x0400,
+  GDK_IM_STATUS_NONE      = 0x0800,
+  GDK_IM_STATUS_MASK      = 0x0f00 
 } GdkIMStyle;
 
 /* The next two enumeration values current match the
@@ -655,15 +658,6 @@ typedef enum
   GDK_FUNC_CLOSE       = 1 << 5
 } GdkWMFunction;
 
-#define GdkIMPreeditMask \
-       ( GdkIMPreeditArea     | GdkIMPreeditCallbacks | \
-         GdkIMPreeditPosition | GdkIMPreeditNothing | \
-         GdkIMPreeditNone )
-
-#define GdkIMStatusMask \
-       ( GdkIMStatusArea | GdkIMStatusCallbacks | \
-         GdkIMStatusNothing | GdkIMStatusNone )
-
 typedef void (*GdkInputFunction) (gpointer         data,
                                  gint              source,
                                  GdkInputCondition condition);
index bd4adfaeeb77a569f15e9987a11c21760048091e..afbcdc4cc92e13f4e8d944794bf087cafa662cb5 100644 (file)
@@ -704,8 +704,10 @@ gdk_window_unref (GdkWindow *window)
     {
       if (!private->destroyed)
        g_warning ("losing last reference to undestroyed window\n");
+      g_dataset_destroy (window);
       g_free (window);
     }
+
 }
 
 void
@@ -2076,3 +2078,11 @@ gdk_window_get_toplevels (void)
   return new_list;
 }
 
+void          
+gdk_drawable_set_data (GdkDrawable   *drawable,
+                      const gchar   *key,
+                      gpointer       data,
+                      GDestroyNotify destroy_func)
+{
+  g_dataset_set_data_full (drawable, key, data, destroy_func);
+}
index 2f43fd85fe57a01013889baca74ad556417b3d17..fbe655d2eaa14d34deacbf1b90ebee171122bec0 100644 (file)
@@ -39,6 +39,8 @@
 
 
 GdkVisual*   gdkx_visual_get   (VisualID xvisualid);
+/* XXX: Do not use this function until it is fixed. An X Colormap
+ *      is useless unless we also have the visual. */
 GdkColormap* gdkx_colormap_get (Colormap xcolormap);
 /* Utility function in gdk.c - not sure where it belongs, but it's
    needed in more than one place, so make it public */
index b17e26a1c5733d1567c4e0536a407a8dc6499e7d..fa810473e60b4df11088435f46795581302904b7 100644 (file)
@@ -16,6 +16,7 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+#include <time.h>
 #include <X11/Xlib.h>
 #include "gdk.h"
 #include "gdkprivate.h"
@@ -52,8 +53,12 @@ gdk_colormap_new (GdkVisual *visual,
 
   private->xdisplay = gdk_display;
   private->visual = visual;
-  private->next_color = 0;
   private->ref_count = 1;
+
+  private->hash = NULL;
+  private->last_sync_time = 0;
+  private->info = NULL;
+  
   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
 
   colormap->size = visual->colormap_size;
@@ -63,6 +68,12 @@ gdk_colormap_new (GdkVisual *visual,
     {
     case GDK_VISUAL_GRAYSCALE:
     case GDK_VISUAL_PSEUDO_COLOR:
+      private->info = g_new0 (GdkColorInfo, colormap->size);
+      colormap->colors = g_new (GdkColor, colormap->size);
+      
+      private->hash = g_hash_table_new (gdk_color_hash,
+                                       gdk_color_equal);
+      
       private->private_val = private_cmap;
       private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
                                            xvisual, (private_cmap) ? (AllocAll) : (AllocNone));
@@ -134,12 +145,15 @@ gdk_colormap_real_destroy (GdkColormap *colormap)
   GdkColormapPrivate *private = (GdkColormapPrivate*) colormap;
 
   g_return_if_fail (colormap != NULL);
-
-  if (private->ref_count > 0)
-    return;
+  g_return_if_fail (private->ref_count > 0);
 
   gdk_colormap_remove (colormap);
   XFreeColormap (private->xdisplay, private->xcolormap);
+
+  if (private->hash)
+    g_hash_table_destroy (private->hash);
+  
+  g_free (private->info);
   g_free (colormap->colors);
   g_free (colormap);
 }
@@ -165,13 +179,61 @@ gdk_colormap_unref (GdkColormap *cmap)
     gdk_colormap_real_destroy (cmap);
 }
 
+#define MIN_SYNC_TIME 2
+
+void
+gdk_colormap_sync (GdkColormap *colormap,
+                  gboolean     force)
+{
+  time_t current_time;
+  GdkColormapPrivate *private = (GdkColormapPrivate *)colormap;
+  XColor *xpalette;
+  gint nlookup;
+  gint i;
+  
+  g_return_if_fail (colormap != NULL);
+
+  current_time = time (NULL);
+  if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME))
+    return;
+
+  private->last_sync_time = current_time;
+
+  nlookup = 0;
+  xpalette = g_new (XColor, colormap->size);
+  
+  for (i = 0; i < colormap->size; i++)
+    {
+      if (private->info[i].ref_count == 0)
+       {
+         xpalette[nlookup].pixel = i;
+         xpalette[nlookup].red = 0;
+         xpalette[nlookup].green = 0;
+         xpalette[nlookup].blue = 0;
+         nlookup++;
+       }
+    }
+  
+  XQueryColors (gdk_display, private->xcolormap, xpalette, nlookup);
+  
+  for (i = 0; i < nlookup; i++)
+    {
+      gulong pixel = xpalette[i].pixel;
+      colormap->colors[pixel].pixel = pixel;
+      colormap->colors[pixel].red = xpalette[i].red;
+      colormap->colors[pixel].green = xpalette[i].green;
+      colormap->colors[pixel].blue = xpalette[i].blue;
+    }
+  
+  g_free (xpalette);
+}
+                  
+
 GdkColormap*
 gdk_colormap_get_system (void)
 {
   static GdkColormap *colormap = NULL;
   GdkColormapPrivate *private;
-  XColor *xpalette;
-  gint i;
 
   if (!colormap)
     {
@@ -182,37 +244,25 @@ gdk_colormap_get_system (void)
       private->xcolormap = DefaultColormap (gdk_display, gdk_screen);
       private->visual = gdk_visual_get_system ();
       private->private_val = FALSE;
-      private->next_color = 0;
       private->ref_count = 1;
 
+      private->hash = NULL;
+      private->last_sync_time = 0;
+      private->info = NULL;
+
+      colormap->colors = NULL;
       colormap->size = private->visual->colormap_size;
-      colormap->colors = g_new (GdkColor, colormap->size);
 
       if ((private->visual->type == GDK_VISUAL_GRAYSCALE) ||
          (private->visual->type == GDK_VISUAL_PSEUDO_COLOR))
        {
-         xpalette = g_new (XColor, colormap->size);
+         private->info = g_new0 (GdkColorInfo, colormap->size);
+         colormap->colors = g_new (GdkColor, colormap->size);
          
-         for (i = 0; i < colormap->size; i++)
-           {
-             xpalette[i].pixel = i;
-             xpalette[i].red = 0;
-             xpalette[i].green = 0;
-             xpalette[i].blue = 0;
-           }
-         
-         XQueryColors (gdk_display, private->xcolormap, xpalette, 
-                       colormap->size);
-         
-         for (i = 0; i < colormap->size; i++)
-           {
-             colormap->colors[i].pixel = xpalette[i].pixel;
-             colormap->colors[i].red = xpalette[i].red;
-             colormap->colors[i].green = xpalette[i].green;
-             colormap->colors[i].blue = xpalette[i].blue;
-           }
+         private->hash = g_hash_table_new (gdk_color_hash,
+                                           gdk_color_equal);
 
-         g_free (xpalette);
+         gdk_colormap_sync (colormap, TRUE);
        }
 
       gdk_colormap_add (colormap);
@@ -258,7 +308,6 @@ gdk_colormap_change (GdkColormap *colormap,
        }
 
       XStoreColors (private->xdisplay, private->xcolormap, palette, ncolors);
-      private->next_color = MAX (private->next_color, ncolors);
       break;
 
     case GDK_VISUAL_DIRECT_COLOR:
@@ -339,6 +388,7 @@ gdk_colors_alloc (GdkColormap   *colormap,
 {
   GdkColormapPrivate *private;
   gint return_val;
+  gint i;
 
   g_return_val_if_fail (colormap != NULL, 0);
 
@@ -347,23 +397,65 @@ gdk_colors_alloc (GdkColormap   *colormap,
   return_val = XAllocColorCells (private->xdisplay, private->xcolormap,
                                 contiguous, planes, nplanes, pixels, npixels);
 
+  if (return_val)
+    {
+      for (i=0; i<npixels; i++)
+       {
+         private->info[pixels[i]].ref_count++;
+         private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
+       }
+    }
+
   return return_val;
 }
 
+/* This is almost identical to gdk_colormap_free_colors.
+ * Keep them in sync!
+ */
 void
 gdk_colors_free (GdkColormap *colormap,
-                gulong      *pixels,
-                gint         npixels,
+                gulong      *in_pixels,
+                gint         in_npixels,
                 gulong       planes)
 {
   GdkColormapPrivate *private;
+  gulong *pixels;
+  gint npixels = 0;
+  gint i;
 
   g_return_if_fail (colormap != NULL);
+  g_return_if_fail (in_pixels != NULL);
 
   private = (GdkColormapPrivate*) colormap;
 
-  XFreeColors (private->xdisplay, private->xcolormap,
-              pixels, npixels, planes);
+  if ((private->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
+      (private->visual->type != GDK_VISUAL_GRAYSCALE))
+    return;
+  
+  pixels = g_new (gulong, in_npixels);
+
+  for (i=0; i<in_npixels; i++)
+    {
+      gulong pixel = in_pixels[i];
+      
+      if (private->info[pixel].ref_count)
+       {
+         private->info[pixel].ref_count--;
+
+         if (private->info[pixel].ref_count == 0)
+           {
+             pixels[npixels++] = pixel;
+             if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
+               g_hash_table_remove (private->hash, &colormap->colors[in_pixels[i]]);
+             private->info[pixel].flags = 0;
+           }
+       }
+    }
+
+  if (npixels)
+    XFreeColors (private->xdisplay, private->xcolormap,
+                pixels, npixels, planes);
+  g_free (pixels);
 }
 
 /*
@@ -494,19 +586,22 @@ gdk_color_parse (const gchar *spec,
   return return_val;
 }
 
-gboolean
-gdk_color_alloc (GdkColormap *colormap,
-                GdkColor    *color)
+/********************
+ * Color allocation *
+ ********************/
+
+/* Try to allocate a single color using XAllocColor. If it succeeds,
+ * cache the result in our colormap, and store in ret.
+ */
+static gboolean 
+gdk_colormap_alloc1 (GdkColormap *colormap,
+                    GdkColor    *color,
+                    GdkColor    *ret)
 {
   GdkColormapPrivate *private;
-  GdkVisual *visual;
   XColor xcolor;
-  gchar *available = NULL;
-  gboolean return_val;
-  gint i, index;
 
-  g_return_val_if_fail (colormap != NULL, FALSE);
-  g_return_val_if_fail (color != NULL, FALSE);
+  private = (GdkColormapPrivate*) colormap;
 
   xcolor.red = color->red;
   xcolor.green = color->green;
@@ -514,113 +609,458 @@ gdk_color_alloc (GdkColormap *colormap,
   xcolor.pixel = color->pixel;
   xcolor.flags = DoRed | DoGreen | DoBlue;
 
-  return_val = FALSE;
+  if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+    {
+      ret->pixel = xcolor.pixel;
+      ret->red = xcolor.red;
+      ret->green = xcolor.green;
+      ret->blue = xcolor.blue;
+      
+      if (ret->pixel < colormap->size)
+       {
+         if (private->info[ret->pixel].ref_count) /* got a duplicate */
+           {
+             XFreeColors (private->xdisplay, private->xcolormap,
+                          &ret->pixel, 1, 0);
+           }
+         else
+           {
+             colormap->colors[ret->pixel] = *color;
+             private->info[ret->pixel].ref_count = 1;
+
+             g_hash_table_insert (private->hash,
+                                  &colormap->colors[ret->pixel],
+                                  &colormap->colors[ret->pixel]);
+           }
+       }
+      return TRUE;
+    }
+  else
+    {
+      return FALSE;
+    }
+}
+
+static gint
+gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
+                                    GdkColor    *colors,
+                                    gint         ncolors,
+                                    gboolean     writeable,
+                                    gboolean     best_match,
+                                    gboolean    *success)
+{
+  GdkColormapPrivate *private;
+  gulong *pixels;
+  Status status;
+  gint i, index;
+
   private = (GdkColormapPrivate*) colormap;
 
-  switch (private->visual->type)
+  if (private->private_val)
     {
-    case GDK_VISUAL_GRAYSCALE:
-    case GDK_VISUAL_PSEUDO_COLOR:
-      if (private->private_val)
+      index = 0;
+      for (i=0; i<ncolors; i++)
        {
-         if (private->next_color >= colormap->size)
+         while ((index < colormap->size) && (private->info[index].ref_count != 0))
+           index++;
+         
+         if (index < colormap->size)
            {
-             available = g_new (gchar, colormap->size);
-             for (i = 0; i < colormap->size; i++)
-               available[i] = TRUE;
-
-             index = gdk_colormap_match_color (colormap, color, available);
-             if (index != -1)
-               {
-                 available[index] = FALSE;
-                 *color = colormap->colors[index];
-                 return_val = TRUE;
-               }
-             else
-               {
-                 return_val = FALSE;
-               }
+             colors[i].pixel = index;
+             success[i] = TRUE;
+             private->info[index].ref_count++;
+             private->info[i].flags |= GDK_COLOR_WRITEABLE;
            }
          else
+           break;
+       }
+      return i;
+    }
+  else
+    {
+      pixels = g_new (gulong, ncolors);
+      /* Allocation of a writeable color cells */
+      
+      status =  XAllocColorCells (private->xdisplay, private->xcolormap,
+                                 FALSE, NULL, 0, pixels, ncolors);
+      if (status)
+       {
+         for (i=0; i<ncolors; i++)
            {
-             xcolor.pixel = colormap->size - 1 -private->next_color;
-             color->pixel = xcolor.pixel;
-             private->next_color += 1;
+             colors[i].pixel = pixels[i];
+             private->info[pixels[i]].ref_count++;
+             private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
+           }
+       }
+      
+      g_free (pixels);
 
-             XStoreColor (private->xdisplay, private->xcolormap, &xcolor);
-             return_val = TRUE;
+      return status ? ncolors : 0; 
+    }
+}
+
+static gint
+gdk_colormap_alloc_colors_private (GdkColormap *colormap,
+                                  GdkColor    *colors,
+                                  gint         ncolors,
+                                  gboolean     writeable,
+                                  gboolean     best_match,
+                                  gboolean    *success)
+{
+  GdkColormapPrivate *private;
+  gint i, index;
+  XColor *store = g_new (XColor, ncolors);
+  gint nstore = 0;
+  gint nremaining = 0;
+  
+  private = (GdkColormapPrivate*) colormap;
+  index = -1;
+
+  /* First, store the colors we have room for */
+
+  index = 0;
+  for (i=0; i<ncolors; i++)
+    {
+      if (!success[i])
+       {
+         while ((index < colormap->size) && (private->info[index].ref_count != 0))
+           index++;
+
+         if (index < colormap->size)
+           {
+             store[nstore].red = colors[i].red;
+             store[nstore].blue = colors[i].blue;
+             store[nstore].green = colors[i].green;
+             store[nstore].pixel = index;
+             nstore++;
+
+             success[i] = TRUE;
+
+             colors[i].pixel = index;
+             private->info[index].ref_count++;
            }
+         else
+           nremaining++;
        }
-      else
+    }
+  
+  XStoreColors (private->xdisplay, private->xcolormap, store, nstore);
+  g_free (store);
+
+  if (nremaining > 0 && best_match)
+    {
+      /* Get best matches for remaining colors */
+
+      gchar *available = g_new (gchar, colormap->size);
+      for (i = 0; i < colormap->size; i++)
+       available[i] = TRUE;
+
+      for (i=0; i<ncolors; i++)
        {
-         while (1)
+         if (!success[i])
            {
-             if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+             index = gdk_colormap_match_color (colormap, 
+                                               &colors[i], 
+                                               available);
+             if (index != -1)
                {
-                 color->pixel = xcolor.pixel;
-                 color->red = xcolor.red;
-                 color->green = xcolor.green;
-                 color->blue = xcolor.blue;
-
-                 if (color->pixel < colormap->size)
-                   colormap->colors[color->pixel] = *color;
+                 colors[i] = colormap->colors[index];
+                 private->info[index].ref_count++;
 
-                 return_val = TRUE;
-                 break;
+                 success[i] = TRUE;
+                 nremaining--;
                }
-             else
-               {
-                 if (available == NULL)
-                   {
-                     available = g_new (gchar, colormap->size);
-                     for (i = 0; i < colormap->size; i++)
-                       available[i] = TRUE;
-                   }
+           }
+       }
+      g_free (available);
+    }
+
+  return (ncolors - nremaining);
+}
+
+static gint
+gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
+                                 GdkColor    *colors,
+                                 gint         ncolors,
+                                 gboolean     writeable,
+                                 gboolean     best_match,
+                                 gboolean    *success)
+{
+  GdkColormapPrivate *private;
+  gint i, index;
+  gint nremaining = 0;
+  gint nfailed = 0;
+
+  private = (GdkColormapPrivate*) colormap;
+  index = -1;
+
+  for (i=0; i<ncolors; i++)
+    {
+      if (!success[i])
+       {
+         if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
+           success[i] = TRUE;
+         else
+           nremaining++;
+       }
+    }
+
 
-                 index = gdk_colormap_match_color (colormap, color, available);
+  if (nremaining > 0 && best_match)
+    {
+      gchar *available = g_new (gchar, colormap->size);
+      for (i = 0; i < colormap->size; i++)
+       available[i] = ((private->info[i].ref_count == 0) ||
+                       !(private->info[i].flags && GDK_COLOR_WRITEABLE));
+      gdk_colormap_sync (colormap, FALSE);
+      
+      while (nremaining > 0)
+       {
+         for (i=0; i<ncolors; i++)
+           {
+             if (!success[i])
+               {
+                 index = gdk_colormap_match_color (colormap, &colors[i], available);
                  if (index != -1)
                    {
-                     available[index] = FALSE;
-                     xcolor.red = colormap->colors[index].red;
-                     xcolor.green = colormap->colors[index].green;
-                     xcolor.blue = colormap->colors[index].blue;
+                     if (private->info[index].ref_count)
+                       {
+                         private->info[index].ref_count++;
+                         colors[i] = colormap->colors[index];
+                         success[i] = TRUE;
+                         nremaining--;
+                       }
+                     else
+                       {
+                         if (gdk_colormap_alloc1 (colormap, 
+                                                  &colormap->colors[index],
+                                                  &colors[i]))
+                           {
+                             success[i] = TRUE;
+                             nremaining--;
+                             break;
+                           }
+                         else
+                           {
+                             available[index] = FALSE;
+                           }
+                       }
                    }
                  else
                    {
-                     return_val = FALSE;
-                     break;
+                     nfailed++;
+                     nremaining--;
+                     success[i] = 2; /* flag as permanent failure */
                    }
                }
            }
        }
+      g_free (available);
+    }
+
+  /* Change back the values we flagged as permanent failures */
+  if (nfailed > 0)
+    {
+      for (i=0; i<ncolors; i++)
+       if (success[i] == 2)
+         success[i] = FALSE;
+      nremaining = nfailed;
+    }
+  
+  return (ncolors - nremaining);
+}
+
+static gint
+gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
+                                      GdkColor    *colors,
+                                      gint         ncolors,
+                                      gboolean     writeable,
+                                      gboolean     best_match,
+                                      gboolean    *success)
+{
+  GdkColormapPrivate *private;
+  GdkColor *lookup_color;
+  gint i;
+  gint nremaining = 0;
+
+  private = (GdkColormapPrivate*) colormap;
+
+  /* Check for an exact match among previously allocated colors */
+
+  for (i=0; i<ncolors; i++)
+    {
+      if (!success[i])
+       {
+         lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
+         if (lookup_color)
+           {
+             private->info[lookup_color->pixel].ref_count++;
+             colors[i].pixel = lookup_color->pixel;
+             success[i] = TRUE;
+           }
+         else
+           nremaining++;
+       }
+    }
+
+  /* If that failed, we try to allocate a new color, or approxmiate
+   * with what we can get if best_match is TRUE.
+   */
+  if (nremaining > 0)
+    {
+      if (private->private_val)
+       return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
+      else
+       return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
+    }
+  else
+    return 0;
+}
+
+gint
+gdk_colormap_alloc_colors (GdkColormap *colormap,
+                          GdkColor    *colors,
+                          gint         ncolors,
+                          gboolean     writeable,
+                          gboolean     best_match,
+                          gboolean    *success)
+{
+  GdkColormapPrivate *private;
+  GdkVisual *visual;
+  gint i;
+  gint nremaining = 0;
+  XColor xcolor;
+
+  g_return_val_if_fail (colormap != NULL, FALSE);
+  g_return_val_if_fail (colors != NULL, FALSE);
+
+  private = (GdkColormapPrivate*) colormap;
+
+  for (i=0; i<ncolors; i++)
+    {
+      success[i] = FALSE;
+    }
+
+  switch (private->visual->type)
+    {
+    case GDK_VISUAL_PSEUDO_COLOR:
+    case GDK_VISUAL_GRAYSCALE:
+      if (writeable)
+       return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
+                                                   writeable, best_match, success);
+      else
+       return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
+                                                   writeable, best_match, success);
       break;
 
     case GDK_VISUAL_DIRECT_COLOR:
+    case GDK_VISUAL_TRUE_COLOR:
       visual = private->visual;
-      xcolor.pixel = (((xcolor.red >> (16 - visual->red_prec)) << visual->red_shift) +
-                     ((xcolor.green >> (16 - visual->green_prec)) << visual->green_shift) +
-                     ((xcolor.blue >> (16 - visual->blue_prec)) << visual->blue_shift));
-      color->pixel = xcolor.pixel;
-      return_val = TRUE;
+
+      for (i=0; i<ncolors; i++)
+       {
+         colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
+                            ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
+                            ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
+         success[i] = TRUE;
+       }
       break;
 
     case GDK_VISUAL_STATIC_GRAY:
     case GDK_VISUAL_STATIC_COLOR:
-    case GDK_VISUAL_TRUE_COLOR:
-      if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+      for (i=0; i<ncolors; i++)
        {
-         color->pixel = xcolor.pixel;
-         return_val = TRUE;
+         xcolor.red = colors[i].red;
+         xcolor.green = colors[i].green;
+         xcolor.blue = colors[i].blue;
+         xcolor.pixel = colors[i].pixel;
+         xcolor.flags = DoRed | DoGreen | DoBlue;
+
+         if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+           {
+             colors[i].pixel = xcolor.pixel;
+             success[i] = TRUE;
+           }
+         else
+           nremaining++;
        }
-      else
-       return_val = FALSE;
       break;
     }
+  return nremaining;
+}
 
-  if (available)
-    g_free (available);
-  
-  return return_val;
+gboolean
+gdk_colormap_alloc_color (GdkColormap *colormap,
+                         GdkColor    *color,
+                         gboolean     writeable,
+                         gboolean     best_match)
+{
+  gboolean success;
+
+  gdk_colormap_alloc_colors (colormap, color, 1, writeable, best_match,
+                            &success);
+
+  return success;
+}
+
+/* This is almost identical to gdk_colors_free.
+ * Keep them in sync!
+ */
+void
+gdk_colormap_free_colors (GdkColormap *colormap,
+                         GdkColor    *colors,
+                         gint         ncolors)
+{
+  GdkColormapPrivate *private;
+  gulong *pixels;
+  gint npixels = 0;
+  gint i;
+
+  g_return_if_fail (colormap != NULL);
+  g_return_if_fail (colors != NULL);
+
+  private = (GdkColormapPrivate*) colormap;
+
+  if ((private->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
+      (private->visual->type != GDK_VISUAL_GRAYSCALE))
+    return;
+
+  pixels = g_new (gulong, ncolors);
+
+  for (i=0; i<ncolors; i++)
+    {
+      gulong pixel = colors[i].pixel;
+      
+      if (private->info[pixel].ref_count)
+       {
+         private->info[pixel].ref_count--;
+
+         if (private->info[pixel].ref_count == 0)
+           {
+             pixels[npixels++] = pixel;
+             if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
+               g_hash_table_remove (private->hash, &colors[i]);
+             private->info[pixel].flags = 0;
+           }
+       }
+    }
+
+  if (npixels)
+    XFreeColors (private->xdisplay, private->xcolormap,
+                pixels, npixels, 0);
+
+  g_free (pixels);
+}
+
+gboolean
+gdk_color_alloc (GdkColormap *colormap,
+                GdkColor    *color)
+{
+  gboolean success;
+
+  gdk_colormap_alloc_colors (colormap, color, 1, FALSE, TRUE, &success);
+
+  return success;
 }
 
 gboolean
@@ -645,9 +1085,19 @@ gdk_color_change (GdkColormap *colormap,
   return TRUE;
 }
 
+guint
+gdk_color_hash (const GdkColor *colora,
+               const GdkColor *colorb)
+{
+  return ((colora->red) +
+         (colora->green << 11) +
+         (colora->blue << 22) +
+         (colora->blue >> 6));
+}
+
 gint
-gdk_color_equal (GdkColor *colora,
-                GdkColor *colorb)
+gdk_color_equal (const GdkColor *colora,
+                const GdkColor *colorb)
 {
   g_return_val_if_fail (colora != NULL, FALSE);
   g_return_val_if_fail (colorb != NULL, FALSE);
@@ -657,6 +1107,9 @@ gdk_color_equal (GdkColor *colora,
          (colora->blue == colorb->blue));
 }
 
+/* XXX: Do not use this function until it is fixed. An X Colormap
+ *      is useless unless we also have the visual.
+ */
 GdkColormap*
 gdkx_colormap_get (Colormap xcolormap)
 {
@@ -677,7 +1130,6 @@ gdkx_colormap_get (Colormap xcolormap)
   private->xcolormap = xcolormap;
   private->visual = NULL;
   private->private_val = TRUE;
-  private->next_color = 0;
 
   /* To do the following safely, we would have to have some way of finding
    * out what the size or visual of the given colormap is. It seems
index 5573d100198ec243502508cf0d087ac9c557b75c..1932d7d3bc51ffbc8aeeb36ba534e339f63dbb69 100644 (file)
@@ -446,15 +446,15 @@ gdk_init (int      *argc,
                  {
                    (*argv)[i++] = NULL;
                    if (strcmp ("none", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMPreeditNone);
+                     gdk_im_set_best_style (GDK_IM_PREEDIT_NONE);
                    else if (strcmp ("nothing", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMPreeditNothing);
+                     gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING);
                    else if (strcmp ("area", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMPreeditArea);
+                     gdk_im_set_best_style (GDK_IM_PREEDIT_AREA);
                    else if (strcmp ("position", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMPreeditPosition);
+                     gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION);
                    else if (strcmp ("callbacks", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMPreeditCallbacks);
+                     gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
                  }
              }
            else if (strcmp ("--xim-status", (*argv)[i]) == 0)
@@ -463,13 +463,13 @@ gdk_init (int      *argc,
                  {
                    (*argv)[i++] = NULL;
                    if (strcmp ("none", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMStatusNone);
+                     gdk_im_set_best_style (GDK_IM_STATUS_NONE);
                    else if (strcmp ("nothing", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMStatusNothing);
+                     gdk_im_set_best_style (GDK_IM_STATUS_NOTHING);
                    else if (strcmp ("area", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMStatusArea);
+                     gdk_im_set_best_style (GDK_IM_STATUS_AREA);
                    else if (strcmp ("callbacks", (*argv)[i]) == 0)
-                     gdk_im_set_best_style (GdkIMStatusCallbacks);
+                     gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
                  }
              }
 #endif
@@ -584,10 +584,10 @@ gdk_init (int      *argc,
   xim_using = FALSE;
   xim_im = NULL;
   xim_styles = NULL;
-  if (!(xim_best_allowed_style & GdkIMPreeditMask))
-    gdk_im_set_best_style (GdkIMPreeditCallbacks);
-  if (!(xim_best_allowed_style & GdkIMStatusMask))
-    gdk_im_set_best_style (GdkIMStatusCallbacks);
+  if (!(xim_best_allowed_style & GDK_IM_PREEDIT_MASK))
+    gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
+  if (!(xim_best_allowed_style & GDK_IM_STATUS_MASK))
+    gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
   xim_ic = NULL;
   xim_window = (GdkWindow*)NULL;
   
@@ -3570,34 +3570,34 @@ gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
   
   if (style1 == 0) return style2;
   if (style2 == 0) return style1;
-  if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask))
-      == (style2 & (GdkIMPreeditMask | GdkIMStatusMask)))
+  if ((style1 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))
+       == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)))
     return style1;
-  
-  s1 = style1 & GdkIMPreeditMask;
-  s2 = style2 & GdkIMPreeditMask;
+
+  s1 = style1 & GDK_IM_PREEDIT_MASK;
+  s2 = style2 & GDK_IM_PREEDIT_MASK;
   u = s1 | s2;
   if (s1 != s2) {
-    if (u & GdkIMPreeditCallbacks)
-      return (s1 == GdkIMPreeditCallbacks)? style1:style2;
-    else if (u & GdkIMPreeditPosition)
-      return (s1 == GdkIMPreeditPosition)? style1:style2;
-    else if (u & GdkIMPreeditArea)
-      return (s1 == GdkIMPreeditArea)? style1:style2;
-    else if (u & GdkIMPreeditNothing)
-      return (s1 == GdkIMPreeditNothing)? style1:style2;
+    if (u & GDK_IM_PREEDIT_CALLBACKS)
+      return (s1 == GDK_IM_PREEDIT_CALLBACKS)? style1:style2;
+    else if (u & GDK_IM_PREEDIT_POSITION)
+      return (s1 == GDK_IM_PREEDIT_POSITION)? style1:style2;
+    else if (u & GDK_IM_PREEDIT_AREA)
+      return (s1 == GDK_IM_PREEDIT_AREA)? style1:style2;
+    else if (u & GDK_IM_PREEDIT_NOTHING)
+      return (s1 == GDK_IM_PREEDIT_NOTHING)? style1:style2;
   } else {
-    s1 = style1 & GdkIMStatusMask;
-    s2 = style2 & GdkIMStatusMask;
+    s1 = style1 & GDK_IM_STATUS_MASK;
+    s2 = style2 & GDK_IM_STATUS_MASK;
     u = s1 | s2;
-    if ( u & GdkIMStatusCallbacks)
-      return (s1 == GdkIMStatusCallbacks)? style1:style2;
-    else if ( u & GdkIMStatusArea)
-      return (s1 == GdkIMStatusArea)? style1:style2;
-    else if ( u & GdkIMStatusNothing)
-      return (s1 == GdkIMStatusNothing)? style1:style2;
-    else if ( u & GdkIMStatusNone)
-      return (s1 == GdkIMStatusNone)? style1:style2;
+    if ( u & GDK_IM_STATUS_CALLBACKS)
+      return (s1 == GDK_IM_STATUS_CALLBACKS)? style1:style2;
+    else if ( u & GDK_IM_STATUS_AREA)
+      return (s1 == GDK_IM_STATUS_AREA)? style1:style2;
+    else if ( u & GDK_IM_STATUS_NOTHING)
+      return (s1 == GDK_IM_STATUS_NOTHING)? style1:style2;
+    else if ( u & GDK_IM_STATUS_NONE)
+      return (s1 == GDK_IM_STATUS_NONE)? style1:style2;
   }
   return 0; /* Get rid of stupid warning */
 }
@@ -3623,39 +3623,39 @@ gdk_im_decide_style (GdkIMStyle supported_style)
 GdkIMStyle
 gdk_im_set_best_style (GdkIMStyle style)
 {
-  if (style & GdkIMPreeditMask)
+  if (style & GDK_IM_PREEDIT_MASK)
     {
-      xim_best_allowed_style &= ~GdkIMPreeditMask;
-      
-      xim_best_allowed_style |= GdkIMPreeditNone;
-      if (!(style & GdkIMPreeditNone))
+      xim_best_allowed_style &= ~GDK_IM_PREEDIT_MASK;
+
+      xim_best_allowed_style |= GDK_IM_PREEDIT_NONE;
+      if (!(style & GDK_IM_PREEDIT_NONE))
        {
-         xim_best_allowed_style |= GdkIMPreeditNothing;
-         if (!(style & GdkIMPreeditNothing))
+         xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING;
+         if (!(style & GDK_IM_PREEDIT_NOTHING))
            {
-             xim_best_allowed_style |= GdkIMPreeditArea;
-             if (!(style & GdkIMPreeditArea))
+             xim_best_allowed_style |= GDK_IM_PREEDIT_AREA;
+             if (!(style & GDK_IM_PREEDIT_AREA))
                {
-                 xim_best_allowed_style |= GdkIMPreeditPosition;
-                 if (!(style & GdkIMPreeditPosition))
-                   xim_best_allowed_style |= GdkIMPreeditCallbacks;
+                 xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION;
+                 if (!(style & GDK_IM_PREEDIT_POSITION))
+                   xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS;
                }
            }
        }
     }
-  if (style & GdkIMStatusMask)
+  if (style & GDK_IM_STATUS_MASK)
     {
-      xim_best_allowed_style &= ~GdkIMStatusMask;
-      
-      xim_best_allowed_style |= GdkIMStatusNone;
-      if (!(style & GdkIMStatusNone))
+      xim_best_allowed_style &= ~GDK_IM_STATUS_MASK;
+
+      xim_best_allowed_style |= GDK_IM_STATUS_NONE;
+      if (!(style & GDK_IM_STATUS_NONE))
        {
-         xim_best_allowed_style |= GdkIMStatusNothing;
-         if (!(style & GdkIMStatusNothing))
+         xim_best_allowed_style |= GDK_IM_STATUS_NOTHING;
+         if (!(style & GDK_IM_STATUS_NOTHING))
            {
-             xim_best_allowed_style |= GdkIMStatusArea;
-             if (!(style & GdkIMStatusArea))
-               xim_best_allowed_style |= GdkIMStatusCallbacks;
+             xim_best_allowed_style |= GDK_IM_STATUS_AREA;
+             if (!(style & GDK_IM_STATUS_AREA))
+               xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS;
            }
        }
     }
@@ -3960,13 +3960,13 @@ gdk_im_end (void)
 GdkIMStyle
 gdk_im_decide_style (GdkIMStyle supported_style)
 {
-  return GdkIMPreeditNone | GdkIMStatusNone;
+  return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
 }
 
 GdkIMStyle
 gdk_im_set_best_style (GdkIMStyle style)
 {
-  return GdkIMPreeditNone | GdkIMStatusNone;
+  return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
 }
 
 gint 
@@ -3991,7 +3991,7 @@ gdk_ic_destroy (GdkIC ic)
 GdkIMStyle
 gdk_ic_get_style (GdkIC ic)
 {
-  return GdkIMPreeditNone | GdkIMStatusNone;
+  return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
 }
 
 void 
index 9fdef0ffcceb18e602c70710df860275d67fcfe3..dfaf4822c94c35b70d00e504c54a98849036c180 100644 (file)
@@ -34,6 +34,13 @@ typedef struct
   gint transparent;
 } _GdkPixmapColor;
 
+typedef struct
+{
+  guint ncolors;
+  GdkColormap *colormap;
+  gulong pixels[1];
+} _GdkPixmapInfo;
+
 GdkPixmap*
 gdk_pixmap_new (GdkWindow *window,
                gint       width,
@@ -388,13 +395,6 @@ gdk_pixmap_extract_color (gchar *buffer)
   return retcol;
 }
 
-static void
-free_color (gpointer key, gpointer value, gpointer user_data)
-{
-  g_free (key);
-  g_free (value);
-}
-  
 
 enum buffer_op
 {
@@ -403,6 +403,23 @@ enum buffer_op
   op_body
 };
   
+
+static void 
+gdk_xpm_destroy_notify (gpointer data)
+{
+  _GdkPixmapInfo *info = (_GdkPixmapInfo *)data;
+  GdkColor color;
+  int i;
+
+  for (i=0; i<info->ncolors; i++)
+    {
+      color.pixel = info->pixels[i];
+      gdk_colormap_free_colors (info->colormap, &color, 1);
+    }
+
+  gdk_colormap_unref (info->colormap);
+  g_free (info);
+}
   
 static GdkPixmap *
 _gdk_pixmap_create_from_xpm (GdkWindow  *window,
@@ -420,9 +437,12 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
   GdkColor tmp_color;
   gint width, height, num_cols, cpp, n, ns, cnt, xcnt, ycnt, wbytes;
   gchar *buffer, pixel_str[32];
+  gchar *name_buf;
   _GdkPixmapColor *color = NULL, *fallbackcolor = NULL;
+  _GdkPixmapColor *colors = NULL;
   gulong index;
-  GHashTable *colors = NULL;
+  GHashTable *color_hash = NULL;
+  _GdkPixmapInfo *color_info = NULL;
   
   if ((window == NULL) && (colormap == NULL))
     g_warning ("Creating pixmap from xpm with NULL window and colormap");
@@ -449,14 +469,30 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
       return NULL;
     }
   
-  colors = g_hash_table_new (g_str_hash, g_str_equal);
+  color_hash = g_hash_table_new (g_str_hash, g_str_equal);
   
   if (transparent_color == NULL)
     {
       gdk_color_white (colormap, &tmp_color);
       transparent_color = &tmp_color;
     }
-  
+
+  /* For pseudo-color and grayscale visuals, we have to remember
+   * the colors we allocated, so we can free them later.
+   */
+  if ((visual->type == GDK_VISUAL_PSEUDO_COLOR) ||
+      (visual->type == GDK_VISUAL_GRAYSCALE))
+    {
+      color_info = g_malloc (sizeof (_GdkPixmapInfo) + 
+                            sizeof(gulong) * (num_cols - 1));
+      color_info->ncolors = num_cols;
+      color_info->colormap = colormap;
+      gdk_colormap_ref (colormap);
+    }
+
+  name_buf = g_new (gchar, num_cols * (cpp+1));
+  colors = g_new (_GdkPixmapColor, num_cols);
+
   for (cnt = 0; cnt < num_cols; cnt++)
     {
       gchar *color_name;
@@ -465,8 +501,8 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
       if (buffer == NULL)
        goto error;
       
-      color = g_new (_GdkPixmapColor, 1);
-      color->color_string = g_new (gchar, cpp + 1);
+      color = &colors[cnt];
+      color->color_string = &name_buf [cnt * (cpp + 1)];
       strncpy (color->color_string, buffer, cpp);
       color->color_string[cpp] = 0;
       buffer += strlen (color->color_string);
@@ -486,7 +522,11 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
       /* FIXME: The remaining slowness appears to happen in this
          function. */
       gdk_color_alloc (colormap, &color->color);
-      g_hash_table_insert (colors, color->color_string, color);
+
+      if (color_info)
+       color_info->pixels[cnt] = color->color.pixel;
+      
+      g_hash_table_insert (color_hash, color->color_string, color);
       if (cnt == 0)
        fallbackcolor = color;
     }
@@ -531,7 +571,7 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
          pixel_str[cpp] = 0;
          ns = 0;
          
-         color = g_hash_table_lookup (colors, pixel_str);
+         color = g_hash_table_lookup (color_hash, pixel_str);
          
          if (!color) /* screwed up XPM file */
            color = fallbackcolor;
@@ -558,6 +598,10 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
   if (image != NULL)
     {
       pixmap = gdk_pixmap_new (window, width, height, visual->depth);
+
+      if (color_info)
+       gdk_drawable_set_data (pixmap, "gdk-xpm", color_info, 
+                              gdk_xpm_destroy_notify);
       
       gc = gdk_gc_new (pixmap);
       gdk_gc_set_foreground (gc, transparent_color);
@@ -565,13 +609,18 @@ _gdk_pixmap_create_from_xpm (GdkWindow  *window,
       gdk_gc_destroy (gc);
       gdk_image_destroy (image);
     }
+  else if (color_info)
+    gdk_xpm_destroy_notify (color_info);
   
+  if (color_hash != NULL)
+    g_hash_table_destroy (color_hash);
+
   if (colors != NULL)
-    {
-      g_hash_table_foreach (colors, free_color, 0);
-      g_hash_table_destroy (colors);
-    }
-  
+    g_free (colors);
+
+  if (name_buf != NULL)
+    g_free (name_buf);
+
   return pixmap;
 }
 
@@ -720,6 +769,7 @@ gdk_pixmap_unref (GdkPixmap *pixmap)
     {
       XFreePixmap (private->xdisplay, private->xwindow);
       gdk_xid_table_remove (private->xwindow);
+      g_dataset_destroy (private);
       g_free (private);
     }
 }
index bd4adfaeeb77a569f15e9987a11c21760048091e..afbcdc4cc92e13f4e8d944794bf087cafa662cb5 100644 (file)
@@ -704,8 +704,10 @@ gdk_window_unref (GdkWindow *window)
     {
       if (!private->destroyed)
        g_warning ("losing last reference to undestroyed window\n");
+      g_dataset_destroy (window);
       g_free (window);
     }
+
 }
 
 void
@@ -2076,3 +2078,11 @@ gdk_window_get_toplevels (void)
   return new_list;
 }
 
+void          
+gdk_drawable_set_data (GdkDrawable   *drawable,
+                      const gchar   *key,
+                      gpointer       data,
+                      GDestroyNotify destroy_func)
+{
+  g_dataset_set_data_full (drawable, key, data, destroy_func);
+}
index 2f43fd85fe57a01013889baca74ad556417b3d17..fbe655d2eaa14d34deacbf1b90ebee171122bec0 100644 (file)
@@ -39,6 +39,8 @@
 
 
 GdkVisual*   gdkx_visual_get   (VisualID xvisualid);
+/* XXX: Do not use this function until it is fixed. An X Colormap
+ *      is useless unless we also have the visual. */
 GdkColormap* gdkx_colormap_get (Colormap xcolormap);
 /* Utility function in gdk.c - not sure where it belongs, but it's
    needed in more than one place, so make it public */
index 024fcf5d0f1a6680ea78b92a805bd79fabe88af4..318334539845bd65def128f0466f291a45b73b9e 100644 (file)
 
 ; enumerations from "../gdk/gdkprivate.h"
 
+(define-flags GdkColorInfoFlags
+   (writeable GDK_COLOR_WRITEABLE))
+
 (define-flags GdkDebugFlag
    (misc GDK_DEBUG_MISC)
    (events GDK_DEBUG_EVENTS)
    (cursor GDK_EXTENSION_EVENTS_CURSOR))
 
 (define-flags GdkIMStyle
-   (preedit-area GdkIMPreeditArea)
-   (preedit-callbacks GdkIMPreeditCallbacks)
-   (preedit-position GdkIMPreeditPosition)
-   (preedit-nothing GdkIMPreeditNothing)
-   (preedit-none GdkIMPreeditNone)
-   (status-area GdkIMStatusArea)
-   (status-callbacks GdkIMStatusCallbacks)
-   (status-nothing GdkIMStatusNothing)
-   (status-none GdkIMStatusNone))
+   (preedit-area GDK_IM_PREEDIT_AREA)
+   (preedit-callbacks GDK_IM_PREEDIT_CALLBACKS)
+   (preedit-position GDK_IM_PREEDIT_POSITION)
+   (preedit-nothing GDK_IM_PREEDIT_NOTHING)
+   (preedit-none GDK_IM_PREEDIT_NONE)
+   (preedit-mask GDK_IM_PREEDIT_MASK)
+   (status-area GDK_IM_STATUS_AREA)
+   (status-callbacks GDK_IM_STATUS_CALLBACKS)
+   (status-nothing GDK_IM_STATUS_NOTHING)
+   (status-none GDK_IM_STATUS_NONE)
+   (status-mask GDK_IM_STATUS_MASK))
 
 (define-flags GdkWMDecoration
    (all GDK_DECOR_ALL)
index 613d64239cc04debafa44547597317275a4b452d..5aaaf25a0b165f5f521d9dbd16980d03d1c35823 100644 (file)
@@ -587,17 +587,17 @@ gtk_entry_realize (GtkWidget *widget)
       gint width, height;
       GdkEventMask mask;
       GdkIMStyle style;
-      GdkIMStyle supported_style = GdkIMPreeditNone | GdkIMPreeditNothing |
-                       GdkIMPreeditPosition |
-                       GdkIMStatusNone | GdkIMStatusNothing;
+      GdkIMStyle supported_style = GDK_IM_PREEDIT_NONE | GDK_IM_PREEDIT_NOTHING |
+                       GDK_IM_PREEDIT_POSITION |
+                       GDK_IM_STATUS_NONE | GDK_IM_STATUS_NOTHING;
 
       if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
-       supported_style &= ~GdkIMPreeditPosition;
+       supported_style &= ~GDK_IM_PREEDIT_POSITION;
 
       style = gdk_im_decide_style (supported_style);
-      switch (style & GdkIMPreeditMask)
+      switch (style & GDK_IM_PREEDIT_MASK)
        {
-       case GdkIMPreeditPosition:
+       case GDK_IM_PREEDIT_POSITION:
          if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
            {
              g_warning ("over-the-spot style requires fontset");
@@ -768,7 +768,7 @@ gtk_entry_size_allocate (GtkWidget     *widget,
       gtk_entry_adjust_scroll (entry);
       
 #ifdef USE_XIM
-      if (editable->ic && (gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition))
+      if (editable->ic && (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION))
        {
          gint width, height;
          GdkRectangle rect;
@@ -1442,7 +1442,7 @@ gtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable)
       gdk_draw_line (drawable, gc, xoffset, 0, xoffset, text_area_height);
 #ifdef USE_XIM
       if (gdk_im_ready() && editable->ic && 
-         gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition)
+         gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)
        {
          GdkPoint spot;
 
index 8600627dd0796690dc1b3538ed69ee029ba73229..856eb27887946ed58c2480e3a0615440b4b29613 100644 (file)
@@ -73,6 +73,8 @@ struct _GtkMenuClass
 
 GtkType           gtk_menu_get_type              (void);
 GtkWidget* gtk_menu_new                          (void);
+
+/* Wrappers for the Menu Shell operations */
 void      gtk_menu_append                (GtkMenu             *menu,
                                           GtkWidget           *child);
 void      gtk_menu_prepend               (GtkMenu             *menu,
@@ -80,6 +82,8 @@ void     gtk_menu_prepend               (GtkMenu             *menu,
 void      gtk_menu_insert                (GtkMenu             *menu,
                                           GtkWidget           *child,
                                           gint                 position);
+
+/* Display the menu onscreen */
 void      gtk_menu_popup                 (GtkMenu             *menu,
                                           GtkWidget           *parent_menu_shell,
                                           GtkWidget           *parent_menu_item,
@@ -87,17 +91,39 @@ void           gtk_menu_popup                 (GtkMenu             *menu,
                                           gpointer             data,
                                           guint                button,
                                           guint32              activate_time);
+
+/* Position the menu according to it's position function. Called
+ * from gtkmenuitem.c when a menu-item changes its allocation
+ */
 void      gtk_menu_reposition            (GtkMenu             *menu);
+
 void      gtk_menu_popdown               (GtkMenu             *menu);
+
+/* Keep track of the last menu item selected. (For the purposes
+ * of the option menu
+ */
 GtkWidget* gtk_menu_get_active           (GtkMenu             *menu);
 void      gtk_menu_set_active            (GtkMenu             *menu,
                                           guint                index);
+
 void      gtk_menu_set_accel_group       (GtkMenu             *menu,
                                           GtkAccelGroup       *accel_group);
+
+/* A reference count is kept for a widget when it is attached to
+ * a particular widget. This is typically a menu item; it may also
+ * be a widget with a popup menu - for instance, the Notebook widget.
+ */
 void      gtk_menu_attach_to_widget      (GtkMenu             *menu,
                                           GtkWidget           *attach_widget,
                                           GtkMenuDetachFunc    detacher);
+void      gtk_menu_detach                (GtkMenu             *menu);
+
+/* This should be dumped in favor of data set when the menu is popped
+ * up - that is currently in the ItemFactory code, but should be
+ * in the Menu code.
+ */
 GtkWidget* gtk_menu_get_attach_widget    (GtkMenu             *menu);
+
 void      gtk_menu_detach                (GtkMenu             *menu);
 void       gtk_menu_set_tearoff_state    (GtkMenu              *menu,
                                          gboolean              torn_off);
index 2cfed81c596f388fe937ebaff835d44ab24d417e..ba0c1e697de798e7f0625d35fafa499d82434beb 100644 (file)
 #define MARK_NEXT_LIST_PTR(mark)    ((mark)->property->next)
 #define MARK_OFFSET(mark)           ((mark)->offset)
 #define MARK_PROPERTY_LENGTH(mark)  (MARK_CURRENT_PROPERTY(mark)->length)
-#define MARK_CURRENT_FONT(mark)     (((TextProperty*)(mark)->property->data)->font->gdk_font)
-#define MARK_CURRENT_FORE(mark)     (&((TextProperty*)(mark)->property->data)->fore_color)
-#define MARK_CURRENT_BACK(mark)     (&((TextProperty*)(mark)->property->data)->back_color)
 
-#define MARK_CURRENT_TEXT_FONT(m)   (((TextProperty*)(m)->property->data)->font)
+
+#define MARK_CURRENT_FONT(text, mark) \
+  ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_FONT) ? \
+         MARK_CURRENT_PROPERTY(mark)->font->gdk_font : \
+         GTK_WIDGET (text)->style->font)
+#define MARK_CURRENT_FORE(text, mark) \
+  ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_FOREGROUND) ? \
+         &MARK_CURRENT_PROPERTY(mark)->fore_color : \
+         &((GtkWidget *)text)->style->text[((GtkWidget *)text)->state])
+#define MARK_CURRENT_BACK(text, mark) \
+  ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_BACKGROUND) ? \
+         &MARK_CURRENT_PROPERTY(mark)->back_color : \
+         &((GtkWidget *)text)->style->base[((GtkWidget *)text)->state])
+#define MARK_CURRENT_TEXT_FONT(text, mark) \
+  ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_FONT) ? \
+         MARK_CURRENT_PROPERTY(mark)->font : \
+         text->current_font)
+
 #define TEXT_LENGTH(t)              ((t)->text_end - (t)->gap_size)
 #define FONT_HEIGHT(f)              ((f)->ascent + (f)->descent)
 #define LINE_HEIGHT(l)              ((l).font_ascent + (l).font_descent)
@@ -73,7 +87,6 @@
 #define LAST_INDEX(t, m)            ((m).index == TEXT_LENGTH(t))
 #define CACHE_DATA(c)               (*(LineParams*)(c)->data)
 
-typedef struct _TextFont              TextFont;
 typedef struct _TextProperty          TextProperty;
 typedef struct _TabStopMark           TabStopMark;
 typedef struct _PrevTabCont           PrevTabCont;
@@ -96,25 +109,35 @@ struct _SetVerticalScrollData {
   GtkPropertyMark mark;
 };
 
-struct _TextFont
+struct _GtkTextFont
 {
   /* The actual font. */
   GdkFont *gdk_font;
-  
+  guint ref_count;
+
   gint16 char_widths[256];
 };
 
+typedef enum {
+  PROPERTY_FONT =       1 << 0,
+  PROPERTY_FOREGROUND = 1 << 1,
+  PROPERTY_BACKGROUND = 1 << 2
+} TextPropertyFlags;
+
 struct _TextProperty
 {
   /* Font. */
-  TextFont* font;
-  
+  GtkTextFont* font;
+
   /* Background Color. */
   GdkColor back_color;
   
   /* Foreground Color. */
   GdkColor fore_color;
-  
+
+  /* Show which properties are set */
+  TextPropertyFlags flags;
+
   /* Length of this property. */
   guint length;
 };
@@ -213,10 +236,24 @@ static gint  gtk_text_focus_out         (GtkWidget         *widget,
 
 static void move_gap_to_point (GtkText* text);
 static void make_forward_space (GtkText* text, guint len);
+
+/* Property management */
+static GtkTextFont* get_text_font (GdkFont* gfont);
+static void         text_font_unref (GtkTextFont *text_font);
+
 static void insert_text_property (GtkText* text, GdkFont* font,
                                  GdkColor *fore, GdkColor* back, guint len);
+static TextProperty* new_text_property (GtkText *text, GdkFont* font, 
+                                       GdkColor* fore, GdkColor* back, guint length);
+static void destroy_text_property (TextProperty *prop);
+static void init_properties      (GtkText *text);
+static void realize_property     (GtkText *text, TextProperty *prop);
+static void realize_properties   (GtkText *text);
+static void unrealize_property   (GtkText *text, TextProperty *prop);
+static void unrealize_properties (GtkText *text);
+
 static void delete_text_property (GtkText* text, guint len);
-static void init_properties (GtkText *text);
+
 static guint pixel_height_of (GtkText* text, GList* cache_line);
 
 /* Property Movement and Size Computations */
@@ -229,7 +266,6 @@ static GtkPropertyMark find_mark (GtkText* text, guint mark_position);
 static GtkPropertyMark find_mark_near (GtkText* text, guint mark_position, const GtkPropertyMark* near);
 static void find_line_containing_point (GtkText* text, guint point,
                                        gboolean scroll);
-static TextProperty* new_text_property (GdkFont* font, GdkColor* fore, GdkColor* back, guint length);
 
 /* Display */
 static void compute_lines_pixels (GtkText* text, guint char_count,
@@ -551,6 +587,10 @@ gtk_text_init (GtkText *text)
   text->timer = 0;
   text->button = 0;
   
+  text->current_font = NULL;
+
+  init_properties (text);
+
   GTK_EDITABLE(text)->editable = FALSE;
 }
 
@@ -745,10 +785,7 @@ gtk_text_insert (GtkText    *text,
   
   g_return_if_fail (text != NULL);
   g_return_if_fail (GTK_IS_TEXT (text));
-  
-  /* This must be because we need to have the style set up. */
-  g_assert (GTK_WIDGET_REALIZED(text));
-  
+
   if (nchars < 0)
     length = strlen (chars);
   else
@@ -763,11 +800,6 @@ gtk_text_insert (GtkText    *text,
       frozen = TRUE;
     }
   
-  if (fore == NULL)
-    fore = &GTK_WIDGET (text)->style->text[GTK_STATE_NORMAL];
-  if (back == NULL)
-    back = &GTK_WIDGET (text)->style->base[GTK_STATE_NORMAL];
-  
   if (!text->freeze && (text->line_start_cache != NULL))
     {
       find_line_containing_point (text, text->point.index, TRUE);
@@ -789,12 +821,8 @@ gtk_text_insert (GtkText    *text,
     text->cursor_mark.index += length;
   
   move_gap_to_point (text);
-  
-  if (font == NULL)
-    font = GTK_WIDGET (text)->style->font;
-  
+
   make_forward_space (text, length);
-  
   memcpy (text->text + text->gap_position, chars, length);
   
   insert_text_property (text, font, fore, back, length);
@@ -1010,9 +1038,11 @@ gtk_text_finalize (GtkObject *object)
   tmp_list = text->text_properties;
   while (tmp_list)
     {
-      g_mem_chunk_free (text_property_chunk, tmp_list->data);
+      destroy_text_property (tmp_list->data);
       tmp_list = tmp_list->next;
     }
+
+  text_font_unref (text->current_font);
   
   g_list_free (text->text_properties);
   
@@ -1096,17 +1126,19 @@ gtk_text_realize (GtkWidget *widget)
       gint width, height;
       GdkEventMask mask;
       GdkIMStyle style;
-      GdkIMStyle supported_style = GdkIMPreeditNone | GdkIMPreeditNothing |
-       GdkIMPreeditPosition |
-       GdkIMStatusNone | GdkIMStatusNothing;
+      GdkIMStyle supported_style = GDK_IM_PREEDIT_NONE | 
+                                  GDK_IM_PREEDIT_NOTHING |
+                                  GDK_IM_PREEDIT_POSITION |
+                                  GDK_IM_STATUS_NONE |
+                                  GDK_IM_STATUS_NOTHING;
       
       if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
-       supported_style &= ~GdkIMPreeditPosition;
+       supported_style &= ~GDK_IM_PREEDIT_POSITION;
       
       style = gdk_im_decide_style (supported_style);
-      switch (style & GdkIMPreeditMask)
+      switch (style & GDK_IM_PREEDIT_MASK)
        {
-       case GdkIMPreeditPosition:
+       case GDK_IM_PREEDIT_POSITION:
          if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
            {
              g_warning ("over-the-spot style requires fontset");
@@ -1152,11 +1184,11 @@ gtk_text_realize (GtkWidget *widget)
        }
     }
 #endif
-  
-  init_properties (text);
 
+  realize_properties (text);
   gdk_window_show (text->text_area);
-  
+  init_properties (text);
+
   if (editable->selection_start_pos != editable->selection_end_pos)
     gtk_editable_claim_selection (editable, TRUE, GDK_CURRENT_TIME);
   
@@ -1182,7 +1214,11 @@ gtk_text_style_set       (GtkWidget      *widget,
       if ((widget->allocation.width > 1) || (widget->allocation.height > 1))
        recompute_geometry (text);
     }
-  
+
+  if (text->current_font)
+    text_font_unref (text->current_font);
+  text->current_font = get_text_font (widget->style->font);
+
   if (GTK_WIDGET_DRAWABLE (widget))
     gdk_window_clear (widget->window);
 }
@@ -1206,7 +1242,9 @@ gtk_text_unrealize (GtkWidget *widget)
   
   gdk_pixmap_unref (text->line_wrap_bitmap);
   gdk_pixmap_unref (text->line_arrow_bitmap);
-  
+
+  unrealize_properties (text);
+
   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
 }
@@ -1399,7 +1437,7 @@ gtk_text_size_allocate (GtkWidget     *widget,
                                                           TEXT_BORDER_ROOM) * 2);
       
 #ifdef USE_XIM
-      if (editable->ic && (gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition))
+      if (editable->ic && (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION))
        {
          gint width, height;
          GdkRectangle rect;
@@ -1703,14 +1741,20 @@ gtk_text_insert_text    (GtkEditable       *editable,
                         gint              *position)
 {
   GtkText *text = GTK_TEXT (editable);
-  
+  GdkFont *font;
+  GdkColor *fore, *back;
+
+  TextProperty *property;
+
   gtk_text_set_point (text, *position);
-  gtk_text_insert (text,
-                  MARK_CURRENT_FONT (&text->point),
-                  MARK_CURRENT_FORE (&text->point),
-                  MARK_CURRENT_BACK (&text->point),
-                  new_text, new_text_length);
+
+  property = MARK_CURRENT_PROPERTY (&text->point);
+  font = property->flags & PROPERTY_FONT ? property->font->gdk_font : NULL; 
+  fore = property->flags & PROPERTY_FOREGROUND ? &property->fore_color : NULL; 
+  back = property->flags & PROPERTY_BACKGROUND ? &property->back_color : NULL; 
   
+  gtk_text_insert (text, font, fore, back, new_text, new_text_length);
+
   *position = text->point.index;
 }
 
@@ -2649,31 +2693,38 @@ insert_expose (GtkText* text, guint old_pixels, gint nchars,
   TEXT_SHOW(text);
 }
 
+/* Text property functions */
+
 static guint
 font_hash (gconstpointer font)
 {
   return gdk_font_id ((const GdkFont*) font);
 }
 
-static TextFont*
+static GHashTable *font_cache_table = NULL;
+
+static GtkTextFont*
 get_text_font (GdkFont* gfont)
 {
-  static GHashTable *font_cache_table = NULL;
-  TextFont* tf;
-  gpointer lu;
+  GtkTextFont* tf;
   gint i;
   
   if (!font_cache_table)
     font_cache_table = g_hash_table_new (font_hash, (GCompareFunc) gdk_font_equal);
   
-  lu = g_hash_table_lookup (font_cache_table, gfont);
-  
-  if (lu)
-    return (TextFont*)lu;
-  
-  tf = g_new (TextFont, 1);
+  tf = g_hash_table_lookup (font_cache_table, gfont);
   
+  if (tf)
+    {
+      tf->ref_count++;
+      return tf;
+    }
+
+  tf = g_new (GtkTextFont, 1);
+  tf->ref_count = 1;
+
   tf->gdk_font = gfont;
+  gdk_font_ref (gfont);
   
   for(i = 0; i < 256; i += 1)
     tf->char_widths[i] = gdk_char_width (gfont, (char)i);
@@ -2683,16 +2734,115 @@ get_text_font (GdkFont* gfont)
   return tf;
 }
 
+static void
+text_font_unref (GtkTextFont *text_font)
+{
+  text_font->ref_count--;
+  if (text_font->ref_count == 0)
+    {
+      g_hash_table_remove (font_cache_table, text_font->gdk_font);
+      gdk_font_unref (text_font->gdk_font);
+      g_free (text_font);
+    }
+}
+
 static gint
 text_properties_equal (TextProperty* prop, GdkFont* font, GdkColor *fore, GdkColor *back)
 {
-  return prop->font == get_text_font(font) &&
-    gdk_color_equal(&prop->fore_color, fore) &&
-    gdk_color_equal(&prop->back_color, back);
+  if (prop->flags & PROPERTY_FONT)
+    {
+      gboolean retval;
+      GtkTextFont *text_font;
+
+      if (!font)
+       return FALSE;
+
+      text_font = get_text_font (font);
+
+      retval = (prop->font == text_font);
+      text_font_unref (text_font);
+      
+      if (!retval)
+       return FALSE;
+    }
+  else
+    if (font != NULL)
+      return FALSE;
+
+  if (prop->flags & PROPERTY_FOREGROUND)
+    {
+      if (!fore || !gdk_color_equal (&prop->fore_color, fore))
+       return FALSE;
+    }
+  else
+    if (fore != NULL)
+      return FALSE;
+
+  if (prop->flags & PROPERTY_BACKGROUND)
+    {
+      if (!back || !gdk_color_equal (&prop->fore_color, fore))
+       return FALSE;
+    }
+  else
+    if (fore != NULL)
+      return FALSE;
+  
+  return TRUE;
+}
+
+static void
+realize_property (GtkText *text, TextProperty *prop)
+{
+  GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (text));
+
+  if (prop->flags & PROPERTY_FOREGROUND)
+    gdk_colormap_alloc_color (colormap, &prop->fore_color, FALSE, FALSE);
+  
+  if (prop->flags & PROPERTY_BACKGROUND)
+    gdk_colormap_alloc_color (colormap, &prop->back_color, FALSE, FALSE);
+}
+
+static void
+realize_properties (GtkText *text)
+{
+  GList *tmp_list = text->text_properties;
+
+  while (tmp_list)
+    {
+      realize_property (text, tmp_list->data);
+      
+      tmp_list = tmp_list->next;
+    }
+}
+
+static void
+unrealize_property (GtkText *text, TextProperty *prop)
+{
+  GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (text));
+
+  if (prop->flags & PROPERTY_FOREGROUND)
+    gdk_colormap_free_colors (colormap, &prop->fore_color, 1);
+  
+  if (prop->flags & PROPERTY_BACKGROUND)
+    gdk_colormap_free_colors (colormap, &prop->back_color, 1);
+}
+
+static void
+unrealize_properties (GtkText *text)
+{
+  GList *tmp_list = text->text_properties;
+
+  while (tmp_list)
+    {
+      unrealize_property (text, tmp_list->data);
+
+      tmp_list = tmp_list->next;
+    }
 }
 
 static TextProperty*
-new_text_property (GdkFont* font, GdkColor* fore, GdkColor* back, guint length)
+new_text_property (GtkText *text, GdkFont *font, GdkColor* fore, 
+                  GdkColor* back, guint length)
 {
   TextProperty *prop;
   
@@ -2705,16 +2855,45 @@ new_text_property (GdkFont* font, GdkColor* fore, GdkColor* back, guint length)
     }
   
   prop = g_chunk_new(TextProperty, text_property_chunk);
+
+  prop->flags = 0;
+  if (font)
+    {
+      prop->flags |= PROPERTY_FONT;
+      prop->font = get_text_font (font);
+    }
+  else
+    prop->font = NULL;
   
-  prop->font = get_text_font (font);
-  prop->fore_color = *fore;
+  if (fore)
+    {
+      prop->flags |= PROPERTY_FOREGROUND;
+      prop->fore_color = *fore;
+    }
+      
   if (back)
-    prop->back_color = *back;
+    {
+      prop->flags |= PROPERTY_BACKGROUND;
+      prop->back_color = *back;
+    }
+
   prop->length = length;
-  
+
+  if (GTK_WIDGET_REALIZED (text))
+    realize_property (text, prop);
+
   return prop;
 }
 
+static void
+destroy_text_property (TextProperty *prop)
+{
+  if (prop->font)
+    text_font_unref (prop->font);
+  
+  g_mem_chunk_free (text_property_chunk, prop);
+}
+
 /* Flop the memory between the point and the gap around like a
  * dead fish. */
 static void
@@ -2809,10 +2988,33 @@ insert_text_property (GtkText* text, GdkFont* font,
               (forward_prop->length == 1))
        {
          /* Next property just has last position, take it over */
-         forward_prop->font = get_text_font (font);
-         forward_prop->fore_color = *fore;
-         forward_prop->back_color = *back;
+
+         if (GTK_WIDGET_REALIZED (text))
+           unrealize_property (text, forward_prop);
+
+         forward_prop->flags = 0;
+         if (font)
+           {
+             forward_prop->flags |= PROPERTY_FONT;
+             forward_prop->font = get_text_font (font);
+           }
+         else
+           forward_prop->font = NULL;
+           
+         if (fore)
+           {
+             forward_prop->flags |= PROPERTY_FOREGROUND;
+             forward_prop->fore_color = *fore;
+           }
+         if (back)
+           {
+             forward_prop->flags |= PROPERTY_BACKGROUND;
+             forward_prop->back_color = *back;
+           }
          forward_prop->length += len;
+
+         if (GTK_WIDGET_REALIZED (text))
+           realize_property (text, forward_prop);
        }
       else
        {
@@ -2826,9 +3028,9 @@ insert_text_property (GtkText* text, GdkFont* font,
          
          if (new_prop->prev)
            new_prop->prev->next = new_prop;
-         
-         new_prop->data = new_text_property (font, fore, back, len);
-         
+
+         new_prop->data = new_text_property (text, font, fore, back, len);
+
          SET_PROPERTY_MARK (mark, new_prop, 0);
        }
     }
@@ -2854,7 +3056,7 @@ insert_text_property (GtkText* text, GdkFont* font,
          forward_prop->length -= 1;
          
          new_prop = g_list_alloc();
-         new_prop->data = new_text_property (font, fore, back, len+1);
+         new_prop->data = new_text_property (text, font, fore, back, len+1);
          new_prop->prev = MARK_LIST_PTR(mark);
          new_prop->next = NULL;
          MARK_NEXT_LIST_PTR(mark) = new_prop;
@@ -2871,14 +3073,19 @@ insert_text_property (GtkText* text, GdkFont* font,
          /* Set the new lengths according to where they are split.  Construct
           * two new properties. */
          forward_prop->length = MARK_OFFSET(mark);
-         
-         new_prop_forward->data = new_text_property(forward_prop->font->gdk_font,
-                                                    &forward_prop->fore_color,
-                                                    &forward_prop->back_color,
-                                                    old_length - forward_prop->length);
-         
-         new_prop->data = new_text_property(font, fore, back, len);
-         
+
+         new_prop_forward->data = 
+           new_text_property(text,
+                             forward_prop->flags & PROPERTY_FONT ? 
+                                     forward_prop->font->gdk_font : NULL,
+                             forward_prop->flags & PROPERTY_FOREGROUND ? 
+                                    &forward_prop->fore_color : NULL,
+                             forward_prop->flags & PROPERTY_BACKGROUND ? 
+                                    &forward_prop->back_color : NULL,
+                             old_length - forward_prop->length);
+
+         new_prop->data = new_text_property(text, font, fore, back, len);
+
          /* Now splice things in. */
          MARK_NEXT_LIST_PTR(mark) = new_prop;
          new_prop->prev = MARK_LIST_PTR(mark);
@@ -2942,8 +3149,11 @@ delete_text_property (GtkText* text, guint nchars)
          
          MARK_LIST_PTR (&text->point) = g_list_remove_link (tmp, tmp);
          text->point.offset = 0;
-         
-         g_mem_chunk_free (text_property_chunk, prop);
+
+         if (GTK_WIDGET_REALIZED (text))
+           unrealize_property (text, prop);
+
+         destroy_text_property (prop);
          g_list_free_1 (tmp);
          
          prop = MARK_CURRENT_PROPERTY (&text->point);
@@ -2976,7 +3186,10 @@ delete_text_property (GtkText* text, guint nchars)
       
       text->point.offset = MARK_CURRENT_PROPERTY(&text->point)->length - 1;
       
-      g_mem_chunk_free (text_property_chunk, prop);
+      if (GTK_WIDGET_REALIZED (text))
+       unrealize_property (text, prop);
+
+      destroy_text_property (prop);
       g_list_free_1 (tmp);
     }
 }
@@ -2984,17 +3197,12 @@ delete_text_property (GtkText* text, guint nchars)
 static void
 init_properties (GtkText *text)
 {
-  GtkWidget *widget = (GtkWidget *)text;
-  
   if (!text->text_properties)
     {
       text->text_properties = g_list_alloc();
       text->text_properties->next = NULL;
       text->text_properties->prev = NULL;
-      text->text_properties->data = new_text_property (widget->style->font,
-                                                      &widget->style->text[GTK_STATE_NORMAL],
-                                                      &widget->style->base[GTK_STATE_NORMAL],
-                                                      1);
+      text->text_properties->data = new_text_property (text, NULL, NULL, NULL, 1);
       text->text_properties_end = text->text_properties;
       
       SET_PROPERTY_MARK (&text->point, text->text_properties, 0);
@@ -3226,8 +3434,8 @@ find_char_width (GtkText* text, const GtkPropertyMark *mark, const TabStopMark *
     return 0;
   
   ch = GTK_TEXT_INDEX (text, mark->index);
-  char_widths = MARK_CURRENT_TEXT_FONT (mark)->char_widths;
-  
+  char_widths = MARK_CURRENT_TEXT_FONT (text, mark)->char_widths;
+
   if (ch == '\t')
     {
       return tab_mark->to_next_tab * char_widths[' '];
@@ -3300,22 +3508,22 @@ find_cursor_at_line (GtkText* text, const LineParams* start_line, gint pixel_hei
   
 #ifdef USE_XIM
   if (gdk_im_ready() && editable->ic && 
-      gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition)
+      gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)
     {
       GdkPoint spot;
       
       spot.x = text->cursor_pos_x;
       spot.y = text->cursor_pos_y - text->cursor_char_offset;
-      if (MARK_CURRENT_FONT (&mark)->type == GDK_FONT_FONTSET)
+      if (MARK_CURRENT_FONT (text, &mark)->type == GDK_FONT_FONTSET)
        gdk_ic_set_attr (editable->ic, "preeditAttributes", 
-                        "fontSet", GDK_FONT_XFONT (MARK_CURRENT_FONT (&mark)),
+                        "fontSet", GDK_FONT_XFONT (MARK_CURRENT_FONT (text, &mark)),
                         NULL);
       
       gdk_ic_set_attr (editable->ic, "preeditAttributes", 
                       "spotLocation", &spot,
                       "lineSpace", LINE_HEIGHT (*start_line),
-                      "foreground", MARK_CURRENT_FORE (&mark)->pixel,
-                      "background", MARK_CURRENT_BACK (&mark)->pixel,
+                      "foreground", MARK_CURRENT_FORE (text, &mark)->pixel,
+                      "background", MARK_CURRENT_BACK (text, &mark)->pixel,
                       NULL);
     }
 #endif 
@@ -4219,8 +4427,8 @@ find_line_params (GtkText* text,
       g_assert (lp.end.property);
       
       ch   = GTK_TEXT_INDEX (text, lp.end.index);
-      font = MARK_CURRENT_FONT (&lp.end);
-      
+      font = MARK_CURRENT_FONT (text, &lp.end);
+
       if (ch == LINE_DELIM)
        {
          /* Newline doesn't count in computation of line height, even
@@ -4253,7 +4461,7 @@ find_line_params (GtkText* text,
                {
                  /* Here's the tough case, a tab is wrapping. */
                  gint pixels_avail = max_display_pixels - lp.pixel_width;
-                 gint space_width  = MARK_CURRENT_TEXT_FONT(&lp.end)->char_widths[' '];
+                 gint space_width  = MARK_CURRENT_TEXT_FONT(text, &lp.end)->char_widths[' '];
                  gint spaces_avail = pixels_avail / space_width;
                  
                  if (spaces_avail == 0)
@@ -4320,8 +4528,8 @@ find_line_params (GtkText* text,
   if (LAST_INDEX(text, lp.start))
     {
       /* Special case, empty last line. */
-      font = MARK_CURRENT_FONT (&lp.end);
-      
+      font = MARK_CURRENT_FONT (text, &lp.end);
+
       lp.font_ascent = font->ascent;
       lp.font_descent = font->descent;
     }
@@ -4367,11 +4575,11 @@ mark_bg_gc (GtkText* text, const GtkPropertyMark *mark)
       else
        return GTK_WIDGET(text)->style->bg_gc[GTK_STATE_ACTIVE];
     }
-  else if (!gdk_color_equal(MARK_CURRENT_BACK (mark),
+  else if (!gdk_color_equal(MARK_CURRENT_BACK (text, mark),
                            &GTK_WIDGET(text)->style->base[GTK_STATE_NORMAL]))
     
     {
-      gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (mark));
+      gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (text, mark));
       return text->gc;
     }
   return NULL;
@@ -4463,8 +4671,8 @@ draw_line (GtkText* text,
            len = MIN (len, selection_start_pos - mark.index);
          else if (mark.index < selection_end_pos)
            len = MIN (len, selection_end_pos - mark.index);
-         
-         font = MARK_CURRENT_PROPERTY (&mark)->font->gdk_font;
+
+         font = MARK_CURRENT_FONT (text, &mark);
          if (font->type == GDK_FONT_FONT)
            {
              gdk_gc_set_font (text->gc, font);
@@ -4506,11 +4714,11 @@ draw_line (GtkText* text,
            }
          else
            {
-             gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (&mark));
+             gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (text, &mark));
              fg_gc = text->gc;
            }
-         
-         gdk_draw_text (text->text_area, MARK_CURRENT_FONT (&mark),
+
+         gdk_draw_text (text->text_area, MARK_CURRENT_FONT (text, &mark),
                         fg_gc,
                         running_offset,
                         pixel_height,
@@ -4534,9 +4742,9 @@ draw_line (GtkText* text,
              
              gdk_window_get_size (text->text_area, &pixels_remaining, NULL);
              pixels_remaining -= (LINE_WRAP_ROOM + running_offset);
-             
-             space_width = MARK_CURRENT_TEXT_FONT(&mark)->char_widths[' '];
-             
+
+             space_width = MARK_CURRENT_TEXT_FONT(text, &mark)->char_widths[' '];
+
              spaces_avail = pixels_remaining / space_width;
              spaces_avail = MIN (spaces_avail, tab_mark.to_next_tab);
              
@@ -4550,8 +4758,8 @@ draw_line (GtkText* text,
            }
          
          running_offset += tab_mark.to_next_tab *
-           MARK_CURRENT_TEXT_FONT(&mark)->char_widths[' '];
-         
+           MARK_CURRENT_TEXT_FONT(text, &mark)->char_widths[' '];
+
          advance_tab_mark (text, &tab_mark, '\t');
        }
       
@@ -4611,7 +4819,8 @@ static void
 undraw_cursor (GtkText* text, gint absolute)
 {
   GtkEditable *editable = (GtkEditable *)text;
-  
+  GdkGC *gc;
+
   TDEBUG (("in undraw_cursor\n"));
   
   if (absolute)
@@ -4624,10 +4833,11 @@ undraw_cursor (GtkText* text, gint absolute)
       GdkFont* font;
       
       g_assert(text->cursor_mark.property);
-      
-      font = MARK_CURRENT_FONT(&text->cursor_mark);
-      
-      if (GTK_WIDGET (text)->style->bg_pixmap[GTK_STATE_NORMAL])
+
+      font = MARK_CURRENT_FONT(text, &text->cursor_mark);
+      gc = mark_bg_gc (text, &text->cursor_mark);
+
+      if (!gc && (GTK_WIDGET (text)->style->bg_pixmap[GTK_STATE_NORMAL]))
        {
          GdkRectangle rect;
          
@@ -4640,8 +4850,12 @@ undraw_cursor (GtkText* text, gint absolute)
        }
       else
        {
-         gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (&text->cursor_mark));
-         gdk_draw_line (text->text_area, text->gc, text->cursor_pos_x,
+         if (!gc)
+           {
+             gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (text, &text->cursor_mark));
+             gc = text->gc;
+           }
+         gdk_draw_line (text->text_area, gc, text->cursor_pos_x,
                         text->cursor_pos_y - text->cursor_char_offset, text->cursor_pos_x,
                         text->cursor_pos_y - text->cursor_char_offset - font->ascent);
        }
@@ -4650,9 +4864,9 @@ undraw_cursor (GtkText* text, gint absolute)
        {
          if (font->type == GDK_FONT_FONT)
            gdk_gc_set_font (text->gc, font);
-         
-         gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (&text->cursor_mark));
-         
+
+         gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (text, &text->cursor_mark));
+
          gdk_draw_text (text->text_area, font,
                         text->gc,
                         text->cursor_pos_x,
@@ -4670,7 +4884,7 @@ drawn_cursor_min (GtkText* text)
   
   g_assert(text->cursor_mark.property);
   
-  font = MARK_CURRENT_FONT(&text->cursor_mark);
+  font = MARK_CURRENT_FONT(text, &text->cursor_mark);
   
   return text->cursor_pos_y - text->cursor_char_offset - font->ascent;
 }
@@ -4682,7 +4896,7 @@ drawn_cursor_max (GtkText* text)
   
   g_assert(text->cursor_mark.property);
   
-  font = MARK_CURRENT_FONT(&text->cursor_mark);
+  font = MARK_CURRENT_FONT(text, &text->cursor_mark);
   
   return text->cursor_pos_y - text->cursor_char_offset;
 }
@@ -4705,9 +4919,9 @@ draw_cursor (GtkText* text, gint absolute)
       GdkFont* font;
       
       g_assert (text->cursor_mark.property);
-      
-      font = MARK_CURRENT_FONT (&text->cursor_mark);
-      
+
+      font = MARK_CURRENT_FONT (text, &text->cursor_mark);
+
       gdk_gc_set_foreground (text->gc, &GTK_WIDGET (text)->style->text[GTK_STATE_NORMAL]);
       
       gdk_draw_line (text->text_area, text->gc, text->cursor_pos_x,
@@ -5072,8 +5286,20 @@ gtk_text_show_props (GtkText *text,
       TextProperty *p = (TextProperty*)props->data;
       
       proplen += p->length;
-      
-      g_message ("[%d,%p,%p,%ld,%ld] ", p->length, p, p->font, p->fore_color.pixel, p->back_color.pixel);
+
+      g_message ("[%d,%p,", p->length, p);
+      if (p->flags & PROPERTY_FONT)
+       g_message ("%p,", p->font);
+      else
+       g_message ("-,");
+      if (p->flags & PROPERTY_FOREGROUND)
+       g_message ("%ld, ", p->fore_color.pixel);
+      else
+       g_message ("-,");
+      if (p->flags & PROPERTY_BACKGROUND)
+       g_message ("%ld] ", p->back_color.pixel);
+      else
+       g_message ("-] ");
     }
   
   g_message ("\n");
index 1de2de945a15a78c3a5a6404b4ccf67268df8c60..27f4689b7e591305c220758f2c512d48a2d0fccc 100644 (file)
@@ -24,7 +24,6 @@
 #include <gtk/gtkadjustment.h>
 #include <gtk/gtkeditable.h>
 
-
 #ifdef __cplusplus
 extern "C" {
 #pragma }
@@ -37,7 +36,7 @@ extern "C" {
 #define GTK_IS_TEXT(obj)               (GTK_CHECK_TYPE ((obj), GTK_TYPE_TEXT))
 #define GTK_IS_TEXT_CLASS(klass)       (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TEXT))
 
-  
+typedef struct _GtkTextFont       GtkTextFont;
 typedef struct _GtkPropertyMark   GtkPropertyMark;
 typedef struct _GtkText           GtkText;
 typedef struct _GtkTextClass      GtkTextClass;
@@ -147,6 +146,8 @@ struct _GtkText
   GList *tab_stops;
   gint default_tab_width;
 
+  GtkTextFont *current_font;   /* Text font for current style */
+
   /* Timer used for auto-scrolling off ends */
   gint timer;
   
index d75f7b6c0169f8f1050ed58d01d54b31bffd63a6..d8afc47183efa8e3429ff18bc1c7b89c26274ec6 100644 (file)
@@ -55,6 +55,7 @@ extern GtkType GTK_TYPE_TOOLBAR_CHILD_TYPE;
 extern GtkType GTK_TYPE_TREE_VIEW_MODE;
 extern GtkType GTK_TYPE_FUNDAMENTAL_TYPE;
 extern GtkType GTK_TYPE_WIDGET_FLAGS;
+extern GtkType GTK_TYPE_GDK_COLOR_INFO_FLAGS;
 extern GtkType GTK_TYPE_GDK_DEBUG_FLAG;
 extern GtkType GTK_TYPE_GDK_RGB_DITHER;
 extern GtkType GTK_TYPE_GDK_WINDOW_TYPE;
index 53d010f89701fa66c7fc4dfff0314660300a651f..6bbef5a4b2307f5020fdc4b1856ddd42ad34a25d 100644 (file)
@@ -438,6 +438,10 @@ static GtkEnumValue _gtk_widget_flags_values[] = {
   { GTK_BASIC, "GTK_BASIC", "basic" },
   { 0, NULL, NULL }
 };
+static GtkEnumValue _gdk_color_info_flags_values[] = {
+  { GDK_COLOR_WRITEABLE, "GDK_COLOR_WRITEABLE", "writeable" },
+  { 0, NULL, NULL }
+};
 static GtkEnumValue _gdk_debug_flag_values[] = {
   { GDK_DEBUG_MISC, "GDK_DEBUG_MISC", "misc" },
   { GDK_DEBUG_EVENTS, "GDK_DEBUG_EVENTS", "events" },
@@ -865,15 +869,17 @@ static GtkEnumValue _gdk_extension_mode_values[] = {
   { 0, NULL, NULL }
 };
 static GtkEnumValue _gdk_im_style_values[] = {
-  { GdkIMPreeditArea, "GdkIMPreeditArea", "preedit-area" },
-  { GdkIMPreeditCallbacks, "GdkIMPreeditCallbacks", "preedit-callbacks" },
-  { GdkIMPreeditPosition, "GdkIMPreeditPosition", "preedit-position" },
-  { GdkIMPreeditNothing, "GdkIMPreeditNothing", "preedit-nothing" },
-  { GdkIMPreeditNone, "GdkIMPreeditNone", "preedit-none" },
-  { GdkIMStatusArea, "GdkIMStatusArea", "status-area" },
-  { GdkIMStatusCallbacks, "GdkIMStatusCallbacks", "status-callbacks" },
-  { GdkIMStatusNothing, "GdkIMStatusNothing", "status-nothing" },
-  { GdkIMStatusNone, "GdkIMStatusNone", "status-none" },
+  { GDK_IM_PREEDIT_AREA, "GDK_IM_PREEDIT_AREA", "preedit-area" },
+  { GDK_IM_PREEDIT_CALLBACKS, "GDK_IM_PREEDIT_CALLBACKS", "preedit-callbacks" },
+  { GDK_IM_PREEDIT_POSITION, "GDK_IM_PREEDIT_POSITION", "preedit-position" },
+  { GDK_IM_PREEDIT_NOTHING, "GDK_IM_PREEDIT_NOTHING", "preedit-nothing" },
+  { GDK_IM_PREEDIT_NONE, "GDK_IM_PREEDIT_NONE", "preedit-none" },
+  { GDK_IM_PREEDIT_MASK, "GDK_IM_PREEDIT_MASK", "preedit-mask" },
+  { GDK_IM_STATUS_AREA, "GDK_IM_STATUS_AREA", "status-area" },
+  { GDK_IM_STATUS_CALLBACKS, "GDK_IM_STATUS_CALLBACKS", "status-callbacks" },
+  { GDK_IM_STATUS_NOTHING, "GDK_IM_STATUS_NOTHING", "status-nothing" },
+  { GDK_IM_STATUS_NONE, "GDK_IM_STATUS_NONE", "status-none" },
+  { GDK_IM_STATUS_MASK, "GDK_IM_STATUS_MASK", "status-mask" },
   { 0, NULL, NULL }
 };
 static GtkEnumValue _gdk_wm_decoration_values[] = {
index f348794a930bd3e20e981acd81e74c21e17b56d0..b13f05b46e5862140ade69159d0ac22e54b482b8 100644 (file)
     GTK_TYPE_ENUM, _gtk_fundamental_type_values },
   { "GtkWidgetFlags", &GTK_TYPE_WIDGET_FLAGS,
     GTK_TYPE_FLAGS, _gtk_widget_flags_values },
+  { "GdkColorInfoFlags", &GTK_TYPE_GDK_COLOR_INFO_FLAGS,
+    GTK_TYPE_FLAGS, _gdk_color_info_flags_values },
   { "GdkDebugFlag", &GTK_TYPE_GDK_DEBUG_FLAG,
     GTK_TYPE_FLAGS, _gdk_debug_flag_values },
   { "GdkRgbDither", &GTK_TYPE_GDK_RGB_DITHER,
index 921dfeb271b308e370b4b6c3e2e19a661fe20fb8..91b31a50c08eb8b0f8614ef871e251732769ea81 100644 (file)
@@ -55,6 +55,7 @@ GtkType GTK_TYPE_TOOLBAR_CHILD_TYPE = 0;
 GtkType GTK_TYPE_TREE_VIEW_MODE = 0;
 GtkType GTK_TYPE_FUNDAMENTAL_TYPE = 0;
 GtkType GTK_TYPE_WIDGET_FLAGS = 0;
+GtkType GTK_TYPE_GDK_COLOR_INFO_FLAGS = 0;
 GtkType GTK_TYPE_GDK_DEBUG_FLAG = 0;
 GtkType GTK_TYPE_GDK_RGB_DITHER = 0;
 GtkType GTK_TYPE_GDK_WINDOW_TYPE = 0;
index eb420ecde4ba8cf85b2220c16f46cbca2092d7a8..ef1975664da65af17ab0fb92dd27a52a211f7be4 100644 (file)
@@ -3087,15 +3087,19 @@ gtk_widget_get_colormap (GtkWidget *widget)
   
   g_return_val_if_fail (widget != NULL, NULL);
   
-  if (!widget->window)
+  if (widget->window)
     {
-      colormap = gtk_object_get_data (GTK_OBJECT (widget), colormap_key);
+      colormap = gdk_window_get_colormap (widget->window);
+      /* If window was destroyed previously, we'll get NULL here */
       if (colormap)
        return colormap;
-      return gtk_widget_get_default_colormap ();
     }
   
-  return gdk_window_get_colormap (widget->window);
+  colormap = gtk_object_get_data (GTK_OBJECT (widget), colormap_key);
+  if (colormap)
+    return colormap;
+
+  return gtk_widget_get_default_colormap ();
 }
 
 /*****************************************
@@ -3113,15 +3117,19 @@ gtk_widget_get_visual (GtkWidget *widget)
   
   g_return_val_if_fail (widget != NULL, NULL);
   
-  if (!widget->window)
+  if (widget->window)
     {
-      visual = gtk_object_get_data (GTK_OBJECT (widget), visual_key);
+      visual = gdk_window_get_visual (widget->window);
+      /* If window was destroyed previously, we'll get NULL here */
       if (visual)
        return visual;
-      return gtk_widget_get_default_visual ();
     }
   
-  return gdk_window_get_visual (widget->window);
+  visual = gtk_object_get_data (GTK_OBJECT (widget), visual_key);
+  if (visual)
+    return visual;
+
+  return gtk_widget_get_default_visual ();
 }
 
 /*****************************************
index 22cb8990cf49f41a0d00b8590657128ff230d457..f101c15a7ad61fa37f29d57e8a5a916ec1a0bcb3 100644 (file)
@@ -1759,6 +1759,8 @@ create_pixmap (void)
                                           &style->bg[GTK_STATE_NORMAL],
                                           "test.xpm");
       pixmapwid = gtk_pixmap_new (pixmap, mask);
+      gdk_pixmap_unref (pixmap);
+      gdk_pixmap_unref (mask);
 
       label = gtk_label_new ("Pixmap\ntest");
       box3 = gtk_hbox_new (FALSE, 0);
@@ -5186,13 +5188,43 @@ text_toggle_word_wrap (GtkWidget *checkbutton,
                          GTK_TOGGLE_BUTTON(checkbutton)->active);
 }
 
+struct {
+  GdkColor color;
+  gchar *name;
+} text_colors[] = {
+ { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
+ { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
+ { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
+ { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
+ { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
+ { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
+ { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
+ { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
+};
+
+int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
+
 /*
  * GtkText
  */
+void
+text_insert_random (GtkWidget *w, GtkText *text)
+{
+  int i;
+  char c;
+   for (i=0; i<10; i++)
+    {
+      c = 'A' + rand() % ('Z' - 'A');
+      gtk_text_set_point (text, rand() % gtk_text_get_length (text));
+      gtk_text_insert (text, NULL, NULL, NULL, &c, 1);
+    }
+}
 
 void
 create_text (void)
 {
+  int i, j;
+
   static GtkWidget *window = NULL;
   GtkWidget *box1;
   GtkWidget *box2;
@@ -5204,6 +5236,7 @@ create_text (void)
   GtkWidget *hscrollbar;
   GtkWidget *vscrollbar;
   GtkWidget *text;
+  GdkFont *font;
 
   FILE *infile;
 
@@ -5259,7 +5292,27 @@ create_text (void)
 
       gtk_text_freeze (GTK_TEXT (text));
 
-      gtk_widget_realize (text);
+      font = gdk_font_load ("-adobe-courier-medium-r-normal--*-120-*-*-*-*-*-*");
+
+      for (i=0; i<ntext_colors; i++)
+       {
+         gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, 
+                          text_colors[i].name, -1);
+         gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, "\t", -1);
+
+         for (j=0; j<ntext_colors; j++)
+           {
+             gtk_text_insert (GTK_TEXT (text), font,
+                              &text_colors[j].color, &text_colors[i].color,
+                              "XYZ", -1);
+           }
+         gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\n", -1);
+       }
+
+      /* The Text widget will reference count the font, so we
+       * unreference it here
+       */
+      gdk_font_unref (font);
 
       infile = fopen("testgtk.c", "r");
       
@@ -5281,13 +5334,6 @@ create_text (void)
          fclose (infile);
        }
       
-      gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, 
-                      "And even ", -1);
-      gtk_text_insert (GTK_TEXT (text), NULL, &text->style->bg[GTK_STATE_NORMAL], NULL, 
-                      "colored", -1);
-      gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, 
-                      "text", -1);
-
       gtk_text_thaw (GTK_TEXT (text));
 
       hbox = gtk_hbutton_box_new ();
@@ -5319,6 +5365,13 @@ create_text (void)
       gtk_widget_show (box2);
 
 
+      button = gtk_button_new_with_label ("insert random");
+      gtk_signal_connect (GTK_OBJECT (button), "clicked",
+                         GTK_SIGNAL_FUNC(text_insert_random),
+                         GTK_TEXT (text));
+      gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+      gtk_widget_show (button);
+
       button = gtk_button_new_with_label ("close");
       gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                 GTK_SIGNAL_FUNC(gtk_widget_destroy),
index 3427c0a876aa239b108c611e9d23619f7be43532..e4e6ba72c705f829f0ad63bfbcadc3e2628bf31d 100644 (file)
@@ -49,7 +49,7 @@ style "toggle_button" = "button"
 style "text"
 {
   bg_pixmap[NORMAL] = "marble.xpm"
-  text[NORMAL] = { 0.2, 0.2, 1.0 }
+  text[NORMAL] = { 1.0, 1.0, 1.0 }
   fg[NORMAL] = { 1.0, 1.0, 1.0 }
   base[NORMAL] = { 0.0, 0.0, 0.0 }
 }
index d2ea54cd25c8523e6c4aabc228cf8b0abb08691c..ac8ff136a028761b29480cc8830793ad522aafe3 100644 (file)
@@ -369,6 +369,7 @@ main (int argc, char *argv[])
      events for the drawing area */
   gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_ALL);
 
+  GTK_WIDGET_SET_FLAGS (drawing_area, GTK_CAN_FOCUS);
   gtk_widget_grab_focus (drawing_area);
 
   /* .. And create some buttons */
index 22cb8990cf49f41a0d00b8590657128ff230d457..f101c15a7ad61fa37f29d57e8a5a916ec1a0bcb3 100644 (file)
@@ -1759,6 +1759,8 @@ create_pixmap (void)
                                           &style->bg[GTK_STATE_NORMAL],
                                           "test.xpm");
       pixmapwid = gtk_pixmap_new (pixmap, mask);
+      gdk_pixmap_unref (pixmap);
+      gdk_pixmap_unref (mask);
 
       label = gtk_label_new ("Pixmap\ntest");
       box3 = gtk_hbox_new (FALSE, 0);
@@ -5186,13 +5188,43 @@ text_toggle_word_wrap (GtkWidget *checkbutton,
                          GTK_TOGGLE_BUTTON(checkbutton)->active);
 }
 
+struct {
+  GdkColor color;
+  gchar *name;
+} text_colors[] = {
+ { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
+ { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
+ { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
+ { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
+ { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
+ { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
+ { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
+ { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
+};
+
+int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
+
 /*
  * GtkText
  */
+void
+text_insert_random (GtkWidget *w, GtkText *text)
+{
+  int i;
+  char c;
+   for (i=0; i<10; i++)
+    {
+      c = 'A' + rand() % ('Z' - 'A');
+      gtk_text_set_point (text, rand() % gtk_text_get_length (text));
+      gtk_text_insert (text, NULL, NULL, NULL, &c, 1);
+    }
+}
 
 void
 create_text (void)
 {
+  int i, j;
+
   static GtkWidget *window = NULL;
   GtkWidget *box1;
   GtkWidget *box2;
@@ -5204,6 +5236,7 @@ create_text (void)
   GtkWidget *hscrollbar;
   GtkWidget *vscrollbar;
   GtkWidget *text;
+  GdkFont *font;
 
   FILE *infile;
 
@@ -5259,7 +5292,27 @@ create_text (void)
 
       gtk_text_freeze (GTK_TEXT (text));
 
-      gtk_widget_realize (text);
+      font = gdk_font_load ("-adobe-courier-medium-r-normal--*-120-*-*-*-*-*-*");
+
+      for (i=0; i<ntext_colors; i++)
+       {
+         gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, 
+                          text_colors[i].name, -1);
+         gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, "\t", -1);
+
+         for (j=0; j<ntext_colors; j++)
+           {
+             gtk_text_insert (GTK_TEXT (text), font,
+                              &text_colors[j].color, &text_colors[i].color,
+                              "XYZ", -1);
+           }
+         gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\n", -1);
+       }
+
+      /* The Text widget will reference count the font, so we
+       * unreference it here
+       */
+      gdk_font_unref (font);
 
       infile = fopen("testgtk.c", "r");
       
@@ -5281,13 +5334,6 @@ create_text (void)
          fclose (infile);
        }
       
-      gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, 
-                      "And even ", -1);
-      gtk_text_insert (GTK_TEXT (text), NULL, &text->style->bg[GTK_STATE_NORMAL], NULL, 
-                      "colored", -1);
-      gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, 
-                      "text", -1);
-
       gtk_text_thaw (GTK_TEXT (text));
 
       hbox = gtk_hbutton_box_new ();
@@ -5319,6 +5365,13 @@ create_text (void)
       gtk_widget_show (box2);
 
 
+      button = gtk_button_new_with_label ("insert random");
+      gtk_signal_connect (GTK_OBJECT (button), "clicked",
+                         GTK_SIGNAL_FUNC(text_insert_random),
+                         GTK_TEXT (text));
+      gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+      gtk_widget_show (button);
+
       button = gtk_button_new_with_label ("close");
       gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                 GTK_SIGNAL_FUNC(gtk_widget_destroy),
index 3427c0a876aa239b108c611e9d23619f7be43532..e4e6ba72c705f829f0ad63bfbcadc3e2628bf31d 100644 (file)
@@ -49,7 +49,7 @@ style "toggle_button" = "button"
 style "text"
 {
   bg_pixmap[NORMAL] = "marble.xpm"
-  text[NORMAL] = { 0.2, 0.2, 1.0 }
+  text[NORMAL] = { 1.0, 1.0, 1.0 }
   fg[NORMAL] = { 1.0, 1.0, 1.0 }
   base[NORMAL] = { 0.0, 0.0, 0.0 }
 }
index d2ea54cd25c8523e6c4aabc228cf8b0abb08691c..ac8ff136a028761b29480cc8830793ad522aafe3 100644 (file)
@@ -369,6 +369,7 @@ main (int argc, char *argv[])
      events for the drawing area */
   gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_ALL);
 
+  GTK_WIDGET_SET_FLAGS (drawing_area, GTK_CAN_FOCUS);
   gtk_widget_grab_focus (drawing_area);
 
   /* .. And create some buttons */